From 36fde6be191b2e8a4cf4bf054c5b010c456c30a5 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Sat, 3 Jun 2023 02:09:45 +0200 Subject: [PATCH 01/89] feat(nodes): integer id is replaced with external public key --- bucket/ddc_bucket/cdn_cluster/entity.rs | 4 +- bucket/ddc_bucket/cdn_cluster/store.rs | 4 +- bucket/ddc_bucket/cdn_node/store.rs | 2 +- bucket/ddc_bucket/cluster/entity.rs | 21 +- bucket/ddc_bucket/cluster/messages.rs | 69 +-- bucket/ddc_bucket/cluster/store.rs | 4 +- bucket/ddc_bucket/node/entity.rs | 8 +- bucket/ddc_bucket/node/messages.rs | 82 ++-- bucket/ddc_bucket/node/store.rs | 59 +-- bucket/ddc_bucket/tests/test_contract.rs | 586 ++++++++++++----------- bucket/ddc_bucket/topology/store.rs | 32 +- bucket/lib.rs | 57 +-- scripts/sdk/src/abi/ddc_bucket.json | 477 +++++++++++------- 13 files changed, 771 insertions(+), 634 deletions(-) diff --git a/bucket/ddc_bucket/cdn_cluster/entity.rs b/bucket/ddc_bucket/cdn_cluster/entity.rs index 8b12f810..0c9482ff 100644 --- a/bucket/ddc_bucket/cdn_cluster/entity.rs +++ b/bucket/ddc_bucket/cdn_cluster/entity.rs @@ -4,10 +4,10 @@ use ink_prelude::vec::Vec; use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout, PackedAllocate}; use scale::{Decode, Encode}; use ink_primitives::Key; -use crate::ddc_bucket::{AccountId, Balance, NodeId, Result}; +use crate::ddc_bucket::{AccountId, Balance, Result}; use crate::ddc_bucket::cash::{Cash, Payable}; use crate::ddc_bucket::Error::{UnauthorizedClusterManager, InsufficientBalance}; -use crate::ddc_bucket::cdn_node::entity::Resource; +use crate::ddc_bucket::cdn_node::entity::{Resource, NodeId}; use crate::ddc_bucket::params::store::Params; pub type ClusterId = u32; diff --git a/bucket/ddc_bucket/cdn_cluster/store.rs b/bucket/ddc_bucket/cdn_cluster/store.rs index c685af1a..46188ef6 100644 --- a/bucket/ddc_bucket/cdn_cluster/store.rs +++ b/bucket/ddc_bucket/cdn_cluster/store.rs @@ -3,8 +3,8 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; use ink_prelude::vec::Vec; -use crate::ddc_bucket::{AccountId, Error::*, NodeId, Result}; - +use crate::ddc_bucket::{AccountId, Error::*, Result}; +use crate::ddc_bucket::cdn_node::entity::{NodeId}; use super::entity::{CdnCluster, ClusterId}; pub const MAX_VNODES: u32 = 300; diff --git a/bucket/ddc_bucket/cdn_node/store.rs b/bucket/ddc_bucket/cdn_node/store.rs index 8a01a0f1..2a1dc83e 100644 --- a/bucket/ddc_bucket/cdn_node/store.rs +++ b/bucket/ddc_bucket/cdn_node/store.rs @@ -8,7 +8,7 @@ use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; use super::entity::{CdnNode, NodeId}; -pub type NodePublicKey = AccountId; +pub type NodeKey = AccountId; #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(StorageLayout, Debug))] diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 35e435d9..6668f87e 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -6,8 +6,7 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout, PackedAllo use scale::{Decode, Encode}; use ink_primitives::Key; use crate::ddc_bucket::cash::Cash; -use crate::ddc_bucket::node::entity::NodeId; -use crate::ddc_bucket::node::entity::Resource; +use crate::ddc_bucket::node::entity::{Resource, NodeKey}; use crate::ddc_bucket::params::store::Params; use crate::ddc_bucket::Error::UnauthorizedClusterManager; use crate::ddc_bucket::{AccountId, Balance, Error::InsufficientResources, Result}; @@ -24,7 +23,7 @@ pub struct Cluster { pub resource_per_vnode: Resource, pub resource_used: Resource, pub revenues: Cash, - pub node_ids: Vec, + pub node_keys: Vec, pub v_nodes: Vec>, pub total_rent: Balance, } @@ -46,14 +45,14 @@ pub struct ClusterStatus { } impl Cluster { - pub fn new(manager_id: AccountId, v_nodes_arr: &Vec>, node_ids: &Vec) -> Self { + pub fn new(manager_id: AccountId, v_nodes_arr: &Vec>, node_keys: &Vec) -> Self { Cluster { manager_id, resource_per_vnode: 0, resource_used: 0, revenues: Cash(0), v_nodes: v_nodes_arr.clone(), - node_ids: node_ids.clone(), + node_keys: node_keys.clone(), total_rent: 0, } } @@ -76,12 +75,12 @@ impl Cluster { } // v_nodes should be sorted - pub fn replace_v_node(&mut self, v_nodes: Vec, node_id: NodeId) { + pub fn replace_v_node(&mut self, v_nodes: Vec, node_id: NodeKey) { let old_v_nodes = &self.v_nodes; - let old_node_ids = &self.node_ids; + let old_node_keys = &self.node_keys; let mut new_v_nodes = Vec::>::new(); - let mut new_node_ids = Vec::::new(); + let mut new_node_keys = Vec::::new(); let mut new_v_nodes_idx = 0; let mut v_nodes_for_new_node = Vec::::new(); @@ -117,14 +116,14 @@ impl Cluster { } new_v_nodes.push(v_nodes_wrapper); - new_node_ids.push(*old_node_ids.get(wrapper_idx).unwrap()); + new_node_keys.push(*old_node_keys.get(wrapper_idx).unwrap()); } new_v_nodes.push(v_nodes_for_new_node); - new_node_ids.push(node_id); + new_node_keys.push(node_id); self.v_nodes = new_v_nodes; - self.node_ids = new_node_ids; + self.node_keys = new_node_keys; } pub fn only_manager(&self, caller: AccountId) -> Result<()> { diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index dc60b33d..b86b81bd 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -4,7 +4,7 @@ use ink_prelude::vec::Vec; use crate::ddc_bucket::cash::{Cash, Payable}; use crate::ddc_bucket::cluster::entity::{Cluster, ClusterStatus}; -use crate::ddc_bucket::node::entity::{Node, NodeId, Resource}; +use crate::ddc_bucket::node::entity::{Node, NodeKey, Resource}; use crate::ddc_bucket::perm::entity::Permission; use crate::ddc_bucket::perm::store::PermStore; use crate::ddc_bucket::ClusterNodeReplaced; @@ -20,24 +20,24 @@ impl DdcBucket { pub fn message_cluster_create( &mut self, v_nodes: Vec>, - node_ids: Vec, + node_keys: Vec, cluster_params: ClusterParams, ) -> Result { let manager = Self::env().caller(); - let mut nodes = Vec::<(NodeId, &Node)>::new(); - for node_id in &node_ids { - let node = self.nodes.get(*node_id)?; - nodes.push((*node_id, node)); - + let mut nodes = Vec::<(NodeKey, Node)>::new(); + for node_key in &node_keys { + let node = self.nodes.get(*node_key)?; // Verify that the node provider trusts the cluster manager. - Self::only_trusted_manager(&self.perms, manager, node.provider_id)?; + Self::only_trusted_manager(&self.perms, manager, node.provider_id.clone())?; + + nodes.push((*node_key, node)); } - let cluster_id = self.clusters.create(manager, &v_nodes, &node_ids)?; + let cluster_id = self.clusters.create(manager, &v_nodes, &node_keys)?; let rent = self .topology_store - .create_topology(cluster_id, v_nodes, nodes.iter().map(|(id, node)| (*id, *node)).collect())?; + .create_topology(cluster_id, v_nodes, nodes.into_iter().map(|(key, node)| (key, node)).collect())?; self.clusters.get_mut(cluster_id).unwrap().change_rent(rent); @@ -55,26 +55,26 @@ impl DdcBucket { pub fn message_cluster_add_node( &mut self, cluster_id: ClusterId, - node_ids: Vec, + node_keys: Vec, v_nodes: Vec>, ) -> Result<()> { let manager = Self::env().caller(); - let mut nodes = Vec::<(NodeId, &Node)>::new(); - - for node_id in &node_ids { - let node = self.nodes.get(*node_id)?; - nodes.push((*node_id, node)); + let mut nodes = Vec::<(NodeKey, Node)>::new(); + for node_key in &node_keys { + let node = self.nodes.get(*node_key)?; // Verify that the node provider trusts the cluster manager. - Self::only_trusted_manager(&self.perms, manager, node.provider_id)?; + Self::only_trusted_manager(&self.perms, manager, node.provider_id.clone())?; + + nodes.push((*node_key, node)); } // add node and redistribute v_nodes let cluster = self.clusters.get(cluster_id)?; let mut old_v_nodes = Vec::::new(); - for v_node_wrapper in &cluster.v_nodes { - for v_node in v_node_wrapper { + for v_nodes_per_phys_node in &cluster.v_nodes { + for v_node in v_nodes_per_phys_node { old_v_nodes.push(*v_node); } } @@ -82,12 +82,12 @@ impl DdcBucket { // TODO: change v_nodes inside cluster entity let total_rent = self .topology_store - .add_node(cluster_id, &old_v_nodes, &v_nodes, nodes.iter().map(|(id, node)| (*id, *node)).collect())?; + .add_node(cluster_id, &old_v_nodes, &v_nodes, nodes.into_iter().map(|(key, node)| (key, node)).collect())?; let cluster = self.clusters.get_mut(cluster_id)?; cluster.total_rent = total_rent as Balance; cluster.v_nodes = v_nodes; - cluster.node_ids = node_ids; + cluster.node_keys = node_keys; Ok(()) } @@ -103,9 +103,10 @@ impl DdcBucket { for v_nodes_wrapper in &cluster.v_nodes { for &v_node in v_nodes_wrapper { - let node_id = self.topology_store.get(cluster_id, v_node)?; - let node = self.nodes.get_mut(node_id)?; + let node_key = self.topology_store.get(cluster_id, v_node)?; + let mut node = self.nodes.get(node_key)?; node.take_resource(resource)?; + self.nodes.update(node_key, &node)?; } } @@ -121,38 +122,40 @@ impl DdcBucket { &mut self, cluster_id: ClusterId, v_nodes: Vec, - new_node_id: NodeId, + new_node_key: NodeKey, ) -> Result<()> { let cluster = self.clusters.get_mut(cluster_id)?; let manager = Self::only_cluster_manager(cluster)?; // Give back resources to the old node for all its v_nodes for v_node in v_nodes.clone() { - let old_node_id = self.topology_store.get(cluster_id, v_node)?; + let old_node_key = self.topology_store.get(cluster_id, v_node)?; // Give back resources to the old node - let old_node = self.nodes.get_mut(old_node_id)?; + let mut old_node = self.nodes.get(old_node_key)?; old_node.put_resource(cluster.resource_per_vnode); + self.nodes.update(old_node_key, &old_node)?; - let new_node = self.nodes.get_mut(new_node_id)?; + let mut new_node = self.nodes.get(new_node_key)?; // Verify that the provider of the new node trusts the cluster manager. Self::only_trusted_manager(&self.perms, manager, new_node.provider_id)?; // Reserve resources on the new node. new_node.take_resource(cluster.resource_per_vnode)?; + self.nodes.update(new_node_key, &new_node)?; - self.topology_store.save(cluster_id, v_node, new_node_id); + self.topology_store.save(cluster_id, v_node, new_node_key); } self.topology_store - .replace_node(cluster_id, v_nodes.clone(), new_node_id)?; + .replace_node(cluster_id, v_nodes.clone(), new_node_key)?; - cluster.replace_v_node(v_nodes, new_node_id); + cluster.replace_v_node(v_nodes, new_node_key); Self::env().emit_event(ClusterNodeReplaced { cluster_id, - node_id: new_node_id, + node_key: new_node_key, }); Ok(()) } @@ -175,8 +178,8 @@ impl DdcBucket { let per_share = cluster.revenues.peek() / num_shares; cluster.revenues.pay(Payable(per_share * num_shares))?; - for node_id in &cluster.node_ids { - let node = self.nodes.get(*node_id)?; + for node_key in &cluster.node_keys { + let node = self.nodes.get(*node_key)?; Self::send_cash(node.provider_id, Cash(per_share))?; Self::env().emit_event(ClusterDistributeRevenues { diff --git a/bucket/ddc_bucket/cluster/store.rs b/bucket/ddc_bucket/cluster/store.rs index 718ffa70..9f02fd94 100644 --- a/bucket/ddc_bucket/cluster/store.rs +++ b/bucket/ddc_bucket/cluster/store.rs @@ -3,7 +3,7 @@ use ink_prelude::vec::Vec; use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; -use crate::ddc_bucket::node::entity::NodeId; +use crate::ddc_bucket::node::entity::{NodeKey}; use crate::ddc_bucket::{AccountId, Error::*, Result}; use super::entity::{Cluster, ClusterId}; @@ -17,7 +17,7 @@ impl ClusterStore { &mut self, manager_id: AccountId, v_nodes: &Vec>, - node_ids: &Vec, + node_ids: &Vec, ) -> Result { let cluster = Cluster::new(manager_id, v_nodes, node_ids); diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index d58750d8..37274336 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -9,8 +9,7 @@ use ink_storage::traits::KeyPtr; use ink_primitives::Key; pub type ProviderId = AccountId; -pub type NodeId = u32; -pub type NodePublicKey = AccountId; +pub type NodeKey = AccountId; pub type NodeParams = Params; pub type Resource = u32; @@ -21,7 +20,7 @@ pub struct Node { pub rent_per_month: Balance, pub free_resource: Resource, pub node_tag: NodeTag, - pub node_pub_key: NodePublicKey, + pub node_params: NodeParams } // https://use.ink/3.x/ink-vs-solidity#nested-mappings--custom--advanced-structures @@ -57,9 +56,8 @@ impl Default for NodeTag { #[derive(Clone, PartialEq, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] pub struct NodeStatus { - pub node_id: NodeId, + pub node_key: NodeKey, pub node: Node, - pub params: Params, } impl Node { diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index b7238884..ab5709c9 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -1,12 +1,11 @@ //! The public interface to manage Nodes. -use crate::ddc_bucket::node::entity::{NodeStatus, Resource}; +use crate::ddc_bucket::node::entity::{NodeStatus, Resource, NodeKey, NodeParams, NodeTag}; use crate::ddc_bucket::perm::entity::Permission; use crate::ddc_bucket::{AccountId, Balance, DdcBucket, NodeCreated, Result}; use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; -use super::entity::{NodeId, NodeParams, NodeTag}; impl DdcBucket { pub fn message_node_trust_manager( @@ -21,60 +20,58 @@ impl DdcBucket { pub fn message_node_create( &mut self, + node_key: NodeKey, rent_per_month: Balance, node_params: NodeParams, capacity: Resource, node_tag: NodeTag, - pubkey: AccountId, - ) -> Result { + ) -> Result { let provider_id = Self::env().caller(); - let node_id = self + let node_key = self .nodes - .create(provider_id, rent_per_month, capacity, node_tag, pubkey) + .create(node_key, provider_id, rent_per_month, node_params.clone(), capacity, node_tag) .unwrap(); - let params_id = self.node_params.create(node_params.clone())?; - assert_eq!(node_id, params_id); - Self::env().emit_event(NodeCreated { - node_id, + node_key, provider_id, rent_per_month, node_params, }); - Ok(node_id) + + Ok(node_key) } - pub fn message_node_change_tag(&mut self, node_id: NodeId, new_tag: NodeTag) -> Result<()> { + pub fn message_node_change_tag(&mut self, node_key: NodeKey, new_tag: NodeTag) -> Result<()> { let caller = Self::env().caller(); - let node = self.nodes.get_mut(node_id)?; + let mut node = self.nodes.get(node_key)?; node.only_owner(caller)?; - node.change_tag(new_tag); + self.nodes.update(node_key, &node)?; Ok(()) } - pub fn message_node_get(&self, node_id: NodeId) -> Result { - let node = self.nodes.get(node_id)?.clone(); - let params = self.node_params.get(node_id)?.clone(); + pub fn message_node_get(&self, node_key: NodeKey) -> Result { + let node = self.nodes.get(node_key)?; Ok(NodeStatus { - node_id, + node_key, node, - params, }) } pub fn message_node_change_params( &mut self, - node_id: NodeId, - params: NodeParams, + node_key: NodeKey, + node_params: NodeParams, ) -> Result<()> { + let caller = Self::env().caller(); - let node = self.nodes.get(node_id)?; + let mut node = self.nodes.get(node_key)?; node.only_owner(caller)?; - - Self::impl_change_params(&mut self.node_params, node_id, params) + node.node_params = node_params; + self.nodes.update(node_key, &node)?; + Ok(()) } pub fn message_node_list( @@ -84,45 +81,38 @@ impl DdcBucket { filter_provider_id: Option, ) -> (Vec, u32) { let mut nodes = Vec::with_capacity(limit as usize); - for node_id in offset..offset + limit { - let node = match self.nodes.nodes.get(node_id as usize) { + for idx in offset..offset + limit { + let node_key = match self.nodes.keys.get(idx as usize) { None => break, // No more items, stop. - Some(node) => node, + Some(node_key) => node_key.clone(), }; + + let node = self.nodes.nodes.get(node_key).unwrap(); + // Apply the filter if given. if let Some(provider_id) = filter_provider_id { if provider_id != node.provider_id { continue; // Skip non-matches. } } + // Include the complete status of matched items. let status = NodeStatus { - node_id, - node: node.clone(), - params: self.node_params.get(node_id).unwrap().clone(), + node_key, + node, }; + nodes.push(status); } - (nodes, self.nodes.nodes.len().try_into().unwrap()) - } - - pub fn message_node_get_by_pub_key(&self, pubkey: AccountId) -> Result { - let node_id = self.nodes.get_by_pub_key(pubkey).unwrap(); - let node = self.nodes.get(node_id)?.clone(); - let params = self.node_params.get(node_id)?.clone(); - Ok(NodeStatus { - node_id, - node, - params, - }) + (nodes, self.nodes.keys.len().try_into().unwrap()) } - pub fn message_remove_node(&mut self, node_id: NodeId) -> Result<()> { + pub fn message_remove_node(&mut self, node_key: NodeKey) -> Result<()> { let caller = Self::env().caller(); - let node = self.nodes.get_mut(node_id)?; + let node = self.nodes.get(node_key)?; node.only_owner(caller)?; - - self.nodes.remove_node(node_id) + self.nodes.remove(node_key) } + } \ No newline at end of file diff --git a/bucket/ddc_bucket/node/store.rs b/bucket/ddc_bucket/node/store.rs index 607bced9..d3a8e519 100644 --- a/bucket/ddc_bucket/node/store.rs +++ b/bucket/ddc_bucket/node/store.rs @@ -4,64 +4,65 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; use ink_prelude::vec::Vec; use ink_storage::Mapping; -use crate::ddc_bucket::node::entity::Resource; +// use crate::ddc_bucket::node::entity::Resource; use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; -use super::entity::{Node, NodeId, NodeTag}; +use super::entity::{Node, NodeTag, NodeKey, NodeParams, Resource}; #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(StorageLayout, Debug))] pub struct NodeStore { - pub account_node: Mapping, - pub nodes: Vec, + pub nodes: Mapping, + // This vector is temporal and must be replaced with an offchain indexer + pub keys: Vec } impl NodeStore { pub fn create( &mut self, + node_key: AccountId, provider_id: AccountId, rent_per_month: Balance, + node_params: NodeParams, capacity: Resource, node_tag: NodeTag, - pubkey: AccountId, - ) -> Result { - let node_id: NodeId = self.nodes.len().try_into().unwrap(); + ) -> Result { + let node = Node { provider_id, rent_per_month, free_resource: capacity, node_tag, - node_pub_key: pubkey, + node_params }; - let exists = self.account_node.contains(&pubkey); - if exists { - return Err(NodeAlreadyExists); + if self.nodes.contains(&node_key) { + Err(NodeAlreadyExists) + } else { + self.nodes.insert(node_key, &node); + self.keys.push(node_key); + Ok(node_key) } - - self.nodes.push(node); - self.account_node.insert(&pubkey, &node_id); - - Ok(node_id) - } - - pub fn get_by_pub_key(&self, pubkey: AccountId) -> Result { - self.account_node.get(&pubkey).ok_or(NodeDoesNotExist) } - pub fn get(&self, node_id: NodeId) -> Result<&Node> { - self.nodes.get(node_id as usize).ok_or(NodeDoesNotExist) + pub fn get(&self, node_key: NodeKey) -> Result { + self.nodes.get(node_key).ok_or(NodeDoesNotExist) } - pub fn get_mut(&mut self, node_id: NodeId) -> Result<&mut Node> { - self.nodes.get_mut(node_id as usize).ok_or(NodeDoesNotExist) + pub fn update(&mut self, node_key: NodeKey, node: &Node) -> Result<()> { + if !self.nodes.contains(&node_key) { + Err(NodeDoesNotExist) + } else { + self.nodes.insert(node_key, node); + Ok(()) + } } - pub fn remove_node(&mut self, node_id: NodeId) -> Result<()> { - let total_nodes = self.nodes.len(); - let last_node = self.nodes.get(total_nodes - 1).ok_or(NodeDoesNotExist).unwrap(); - self.account_node.insert(&last_node.node_pub_key, &node_id); - self.nodes.swap_remove(node_id.try_into().unwrap()); + pub fn remove(&mut self, node_key: NodeKey) -> Result<()> { + self.nodes.remove(node_key); + if let Some(pos) = self.keys.iter().position(|x| *x == node_key) { + self.keys.remove(pos); + }; Ok(()) } } diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index 53af3e6f..3229f8ae 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -4,7 +4,7 @@ use crate::ddc_bucket::account::entity::Account; use crate::ddc_bucket::cdn_node::entity::NodeId; use crate::ddc_bucket::cluster::entity::ClusterStatus; use crate::ddc_bucket::flow::Flow; -use crate::ddc_bucket::node::entity::NodeTag; +use crate::ddc_bucket::node::entity::{NodeTag, NodeKey}; use crate::ddc_bucket::schedule::{Schedule, MS_PER_MONTH}; use crate::ddc_bucket::Error::*; use crate::ddc_bucket::*; @@ -28,11 +28,11 @@ struct TestCluster { provider_id0: AccountId, provider_id1: AccountId, provider_id2: AccountId, - node_id0: NodeId, - node_id1: NodeId, - node_id2: NodeId, + node_key0: NodeKey, + node_key1: NodeKey, + node_key2: NodeKey, rent_per_vnode: Balance, - node_ids: Vec, + node_keys: Vec, vnodes: Vec, vnodes_wrapper: Vec>, node_params0: &'static str, @@ -66,40 +66,44 @@ fn new_cluster() -> TestCluster { } set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); - let node_id0 = contract.node_create( + let node_key0 = contract.node_create( + AccountId::from([0x0a; 32]), rent_per_vnode, node_params0.to_string(), capacity, NodeTag::ADDING, - provider_id0, ); // Provide another Node. let node_params1 = "{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"; set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); - let node_id1 = contract.node_create( + let node_key1 = contract.node_create( + AccountId::from([0x0b; 32]), rent_per_vnode, node_params1.to_string(), capacity, NodeTag::ADDING, - provider_id1, ); // Provide another Node. let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); - let node_id2 = contract.node_create( + let node_key2 = contract.node_create( + AccountId::from([0x0c; 32]), rent_per_vnode, node_params2.to_string(), capacity, NodeTag::ADDING, - provider_id2, ); // Create a Cluster. - let node_ids = vec![1, 2, 3]; + let node_keys = vec![ + AccountId::from([0x0a; 32]), + AccountId::from([0x0b; 32]), + AccountId::from([0x0c; 32]) + ]; let cluster_params = "{}"; let mut vnodes_wrapper = Vec::>::new(); @@ -116,7 +120,7 @@ fn new_cluster() -> TestCluster { let cluster_id = contract.cluster_create( manager, vnodes_wrapper.clone(), - vec![node_id0, node_id1, node_id2], + vec![node_key0, node_key1, node_key2], cluster_params.to_string(), ); @@ -138,13 +142,13 @@ fn new_cluster() -> TestCluster { provider_id0, provider_id1, provider_id2, - node_id0, - node_id1, - node_id2, + node_key0, + node_key1, + node_key2, rent_per_vnode, vnodes_wrapper, vnodes, - node_ids, + node_keys, node_params0, node_params1, node_params2, @@ -153,102 +157,108 @@ fn new_cluster() -> TestCluster { } } -fn new_cluster_cdn() -> TestCluster { - let accounts = get_accounts(); - set_balance(accounts.charlie, 1000 * TOKEN); - set_balance(accounts.django, 1000 * TOKEN); - let provider_id0 = accounts.alice; - let provider_id1 = accounts.bob; - let provider_id2 = accounts.charlie; - let manager = accounts.django; - - let mut contract = setup(); - - // Provide a Node. - let rent_per_vnode: Balance = 10 * TOKEN; - let node_params0 = "{\"url\":\"https://ddc.cere.network/bucket/{BUCKET_ID}\"}"; - let capacity = 100; - - for provider_id in [provider_id0, provider_id1, provider_id2] { - set_caller_value(provider_id, CONTRACT_FEE_LIMIT); - - contract.node_trust_manager(manager); - let expected_perm = Permission::ManagerTrustedBy(provider_id); - assert!(contract.has_permission(manager, expected_perm)); - } - - set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); - - let node_id0 = contract.cdn_node_create(node_params0.to_string(), provider_id0); - - // Provide another Node. - let node_params1 = "{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"; - set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); - - let node_id1 = contract.cdn_node_create(node_params1.to_string(), provider_id1); - - // Provide another Node. - let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; - set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); - - let node_id2 = contract.cdn_node_create(node_params2.to_string(), provider_id2); - - // Create a Cluster. - let _cluster_params = "{}"; - - // TODO: adjust after cdn cluster topology and node addition - - let vnodes = vec![1, 2, 3, 4, 5, 6]; - - let node_ids = vec![1, 2, 3]; - let mut vnodes_wrapper = Vec::>::new(); - vnodes_wrapper.push(vnodes); - - let mut vnodes_wrapper = Vec::>::new(); - - let vnodes_for_first_node = vec![1, 2, 3]; - let vnodes_for_second_node = vec![4, 5, 6]; - let vnodes_for_third_node = vec![7, 8, 9]; - - vnodes_wrapper.push(vnodes_for_first_node); - vnodes_wrapper.push(vnodes_for_second_node); - vnodes_wrapper.push(vnodes_for_third_node); - - set_caller_value(manager, CONTRACT_FEE_LIMIT); - - let cluster_id = contract.cdn_cluster_create(vec![node_id0, node_id1, node_id2]); - - let reserved = 10; - - let mut vnodes = Vec::::new(); - - for v_nodes_vec in vnodes_wrapper.clone() { - for v_node in v_nodes_vec { - vnodes.push(v_node.clone()); - } - } - - TestCluster { - contract, - manager, - cluster_id, - provider_id0, - provider_id1, - provider_id2, - node_id0, - node_id1, - node_id2, - rent_per_vnode, - vnodes_wrapper, - node_params0, - node_params1, - node_params2, - capacity, - reserved, - node_ids, - vnodes, - } -} +// fn new_cluster_cdn() -> TestCluster { +// let accounts = get_accounts(); +// set_balance(accounts.charlie, 1000 * TOKEN); +// set_balance(accounts.django, 1000 * TOKEN); +// let provider_id0 = accounts.alice; +// let provider_id1 = accounts.bob; +// let provider_id2 = accounts.charlie; +// let manager = accounts.django; + +// let mut contract = setup(); + +// // Provide a Node. +// let rent_per_vnode: Balance = 10 * TOKEN; +// let node_params0 = "{\"url\":\"https://ddc.cere.network/bucket/{BUCKET_ID}\"}"; +// let capacity = 100; + +// for provider_id in [provider_id0, provider_id1, provider_id2] { +// set_caller_value(provider_id, CONTRACT_FEE_LIMIT); + +// contract.node_trust_manager(manager); +// let expected_perm = Permission::ManagerTrustedBy(provider_id); +// assert!(contract.has_permission(manager, expected_perm)); +// } + +// set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); + +// let node_key0 = contract.cdn_node_create(node_params0.to_string(), provider_id0); + +// // Provide another Node. +// let node_params1 = "{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"; +// set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); + +// let node_key1 = contract.cdn_node_create(node_params1.to_string(), provider_id1); + +// // Provide another Node. +// let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; +// set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); + +// let node_key2 = contract.cdn_node_create(node_params2.to_string(), provider_id2); + +// // Create a Cluster. +// let _cluster_params = "{}"; + +// // TODO: adjust after cdn cluster topology and node addition + +// let vnodes = vec![1, 2, 3, 4, 5, 6]; + +// let node_keys = vec![node_key0, node_key1, node_key2]; +// let mut vnodes_wrapper = Vec::>::new(); +// vnodes_wrapper.push(vnodes); + +// let mut vnodes_wrapper = Vec::>::new(); + +// let vnodes_for_first_node = vec![1, 2, 3]; +// let vnodes_for_second_node = vec![4, 5, 6]; +// let vnodes_for_third_node = vec![7, 8, 9]; + +// vnodes_wrapper.push(vnodes_for_first_node); +// vnodes_wrapper.push(vnodes_for_second_node); +// vnodes_wrapper.push(vnodes_for_third_node); + +// set_caller_value(manager, CONTRACT_FEE_LIMIT); + +// let cluster_id = contract.cdn_cluster_create( +// vec![ +// AccountId::from([0x0a; 32]), +// AccountId::from([0x0b; 32]), +// AccountId::from([0x0c; 32]) +// ] +// ); + +// let reserved = 10; + +// let mut vnodes = Vec::::new(); + +// for v_nodes_vec in vnodes_wrapper.clone() { +// for v_node in v_nodes_vec { +// vnodes.push(v_node.clone()); +// } +// } + +// TestCluster { +// contract, +// manager, +// cluster_id, +// provider_id0, +// provider_id1, +// provider_id2, +// node_key0, +// node_key1, +// node_key2, +// rent_per_vnode, +// vnodes_wrapper, +// node_params0, +// node_params1, +// node_params2, +// capacity, +// reserved, +// node_keys, +// vnodes, +// } +// } struct TestBucket { bucket_id: BucketId, @@ -286,61 +296,58 @@ fn new_bucket(ctx: &mut TestCluster) -> TestBucket { fn cluster_create_works() { let ctx = new_cluster(); let provider_ids = &[ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; - let node_ids = &[ctx.node_id0, ctx.node_id1, ctx.node_id2]; + let node_keys = &[ctx.node_key0, ctx.node_key1, ctx.node_key2]; let node_params = &[ctx.node_params0, ctx.node_params1, ctx.node_params2]; assert_eq!(ctx.cluster_id, 1, "cluster_id must start at 1"); - assert_eq!(ctx.node_id0, 1, "node_id must start at 1"); - assert_ne!(ctx.node_id0, ctx.node_id1, "nodes must have unique IDs"); + assert_eq!(ctx.node_key0, AccountId::from([0x0a; 32]), "node_id must start at 1"); + assert_ne!(ctx.node_key0, ctx.node_key1, "nodes must have unique IDs"); // Check the nodes. { - let node0 = ctx.contract.node_get(ctx.node_id0)?; + let node0 = ctx.contract.node_get(ctx.node_key0)?; assert_eq!( node0, NodeStatus { - node_id: ctx.node_id0, + node_key: ctx.node_key0, node: Node { provider_id: ctx.provider_id0, rent_per_month: ctx.rent_per_vnode, free_resource: ctx.capacity - ctx.reserved * 3, node_tag: NodeTag::ADDING, - node_pub_key: ctx.provider_id0, - }, - params: ctx.node_params0.to_string(), + node_params: ctx.node_params0.to_string(), + } } ); - let node1 = ctx.contract.node_get(ctx.node_id1)?; + let node1 = ctx.contract.node_get(ctx.node_key1)?; assert_eq!( node1, NodeStatus { - node_id: ctx.node_id1, + node_key: ctx.node_key1, node: Node { provider_id: ctx.provider_id1, rent_per_month: ctx.rent_per_vnode, free_resource: ctx.capacity - ctx.reserved * 3, node_tag: NodeTag::ADDING, - node_pub_key: ctx.provider_id1, - }, - params: ctx.node_params1.to_string(), + node_params: ctx.node_params1.to_string(), + } } ); - let node2 = ctx.contract.node_get(ctx.node_id2)?; + let node2 = ctx.contract.node_get(ctx.node_key2)?; assert_eq!( node2, NodeStatus { - node_id: ctx.node_id2, + node_key: ctx.node_key2, node: Node { provider_id: ctx.provider_id2, rent_per_month: ctx.rent_per_vnode, free_resource: ctx.capacity - ctx.reserved * 3, node_tag: NodeTag::ADDING, - node_pub_key: ctx.provider_id2, - }, - params: ctx.node_params2.to_string(), + node_params: ctx.node_params2.to_string(), + } } ); } @@ -354,7 +361,7 @@ fn cluster_create_works() { cluster_id: ctx.cluster_id, cluster: Cluster { manager_id: ctx.manager, - node_ids: ctx.node_ids, + node_keys: ctx.node_keys, v_nodes: ctx.vnodes_wrapper, resource_per_vnode: ctx.reserved, resource_used: 0, @@ -382,10 +389,12 @@ fn cluster_create_works() { for i in 0..3 { assert!(matches!(evs.pop().unwrap(), Event::NodeCreated(ev) if ev == NodeCreated { - node_id: node_ids[i], + node_key: node_keys[i], provider_id: provider_ids[i], rent_per_month: ctx.rent_per_vnode, - node_params: node_params[i].to_string() })); + node_params: node_params[i].to_string() + }) + ); } // Cluster setup. @@ -411,7 +420,11 @@ fn cluster_replace_node_only_manager() { // Reassign a vnode from node1 to node2. assert_eq!( ctx.contract - .message_cluster_replace_node(ctx.cluster_id, vec![1, 2, 3], ctx.node_id2), + .message_cluster_replace_node( + ctx.cluster_id, + vec![1, 2, 3], + ctx.node_key2 + ), Err(UnauthorizedClusterManager) ); } @@ -429,7 +442,11 @@ fn cluster_replace_node_only_trusted_manager() { // The manager cannot use nodes of the provider. assert_eq!( ctx.contract - .message_cluster_replace_node(ctx.cluster_id, vec![1, 2, 3], ctx.node_id2), + .message_cluster_replace_node( + ctx.cluster_id, + vec![1, 2, 3], + ctx.node_key2 + ), Err(ClusterManagerIsNotTrusted) ); } @@ -441,12 +458,12 @@ fn cluster_replace_node_works() { // Reassign a vnode from node1 to node2. ctx.contract - .cluster_replace_node(ctx.cluster_id, vec![1, 3], ctx.node_id2); + .cluster_replace_node(ctx.cluster_id, vec![1, 3], ctx.node_key2); // Check the last event. let ev = get_events().pop().unwrap(); assert!(matches!(ev, Event::ClusterNodeReplaced(ev) if ev == - ClusterNodeReplaced { cluster_id: ctx.cluster_id, node_id: ctx.node_id2 })); + ClusterNodeReplaced { cluster_id: ctx.cluster_id, node_key: ctx.node_key2 })); let vnodes_for_replaced = vec![2]; let vnodes_for_second_node = vec![4, 5, 6]; @@ -463,18 +480,18 @@ fn cluster_replace_node_works() { // Check the changed state of the cluster. let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; println!("cluster.v_nodes: {:?}", cluster.v_nodes.clone()); - println!("cluster.node_ids: {:?}", cluster.node_ids.clone()); + println!("cluster.node_keys: {:?}", cluster.node_keys.clone()); assert_eq!(&cluster.v_nodes, &vnodes, "a vnode must be replaced"); // Check the changed state of the nodes. let expected_resources = [ - (ctx.node_id0, 100 - 10), - (ctx.node_id1, 100 - 10 - 10 - 10), - (ctx.node_id2, 100 - 10 - 10 - 10 - 10 - 10), + (ctx.node_key0, 100 - 10), + (ctx.node_key1, 100 - 10 - 10 - 10), + (ctx.node_key2, 100 - 10 - 10 - 10 - 10 - 10), ]; - for (node_id, available) in expected_resources { - let node_status = ctx.contract.node_get(node_id as u32).unwrap(); + for (node_key, available) in expected_resources { + let node_status = ctx.contract.node_get(node_key).unwrap(); assert_eq!( node_status.node.free_resource, available, "resources must have shifted between nodes" @@ -501,9 +518,9 @@ fn cluster_reserve_works() { // Check the changed state of the nodes. let expected_resources = [ - (ctx.node_id0, 100 - 40 - 5), - (ctx.node_id1, 100 - 40 - 5), - (ctx.node_id2, 100 - 40 - 5), + (ctx.node_key0, 100 - 40 - 5), + (ctx.node_key1, 100 - 40 - 5), + (ctx.node_key2, 100 - 40 - 5), ]; for (node_id, available) in expected_resources { assert_eq!( @@ -523,150 +540,160 @@ fn cluster_management_validation_works() { assert_eq!( ctx.contract - .message_cluster_replace_node(ctx.cluster_id, vec![1, 2, 3], 1), + .message_cluster_replace_node( + ctx.cluster_id, + vec![1, 2, 3], + AccountId::from([0x0a; 32]) + ), Err(UnauthorizedClusterManager), "only the manager can modify the cluster" ); set_caller_value(ctx.manager, 0); - let bad_node_id = ctx.node_id2 + 1; + let bad_node_id = AccountId::from([0x0d; 32]); assert_eq!( ctx.contract - .message_cluster_replace_node(ctx.cluster_id, vec![1, 2, 3], bad_node_id), + .message_cluster_replace_node( + ctx.cluster_id, + vec![1, 2, 3], + bad_node_id + ), Err(NodeDoesNotExist), "cluster replacement node must exist" ); assert_eq!( ctx.contract - .message_cluster_create(vec![vec![1, 2, 3]], vec![bad_node_id], "".to_string()), + .message_cluster_create(vec![ + vec![1, 2, 3], + ], vec![bad_node_id], "".to_string()), Err(NodeDoesNotExist), "cluster initial nodes must exist" ); } -#[ink::test] -fn cdn_cluster_gas_converter_works() { - println!("Creating new cdn cluster"); +// #[ink::test] +// fn cdn_cluster_gas_converter_works() { +// println!("Creating new cdn cluster"); - let mut ctx = new_cluster_cdn(); +// let mut ctx = new_cluster_cdn(); - println!("Got cdn cluster back"); - // The provider stops trusting the manager. - println!("Cdn cluster id is {}", ctx.cluster_id); - set_caller(ctx.manager); - ctx.contract.cdn_set_rate(ctx.cluster_id, 3_750_000_000); - set_caller(ctx.provider_id0); - let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); +// println!("Got cdn cluster back"); +// // The provider stops trusting the manager. +// println!("Cdn cluster id is {}", ctx.cluster_id); +// set_caller(ctx.manager); +// ctx.contract.cdn_set_rate(ctx.cluster_id, 3_750_000_000); +// set_caller(ctx.provider_id0); +// let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); - let usd_per_cere = TOKEN / 100; - set_caller(ctx.provider_id0); - ctx.contract.account_set_usd_per_cere(usd_per_cere); +// let usd_per_cere = TOKEN / 100; +// set_caller(ctx.provider_id0); +// ctx.contract.account_set_usd_per_cere(usd_per_cere); - let usd_amount = ctx.contract.account_get_usd_per_cere(); - println!("Current usd amount is {}", usd_amount); +// let usd_amount = ctx.contract.account_get_usd_per_cere(); +// println!("Current usd amount is {}", usd_amount); - println!("The current rate is {}", rate); +// println!("The current rate is {}", rate); - let usd_per_kb = rate / KB_PER_GB; - println!("The current rate per kb {}", usd_per_kb); +// let usd_per_kb = rate / KB_PER_GB; +// println!("The current rate per kb {}", usd_per_kb); - let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); - println!("The current cere rate per kb {}", cere_per_kb); -} +// let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); +// println!("The current cere rate per kb {}", cere_per_kb); +// } -#[ink::test] -fn cdn_cluster_payment_works() { - println!("Creating new cdn cluster"); +// #[ink::test] +// fn cdn_cluster_payment_works() { +// println!("Creating new cdn cluster"); - let mut ctx = new_cluster_cdn(); +// let mut ctx = new_cluster_cdn(); - println!("Got cdn cluster back"); - // The provider stops trusting the manager. - println!("Cdn cluster id is {}", ctx.cluster_id); - set_caller(ctx.provider_id0); - let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); +// println!("Got cdn cluster back"); +// // The provider stops trusting the manager. +// println!("Cdn cluster id is {}", ctx.cluster_id); +// set_caller(ctx.provider_id0); +// let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); - let usd_per_cere = TOKEN / 100; - set_caller(ctx.provider_id0); - ctx.contract.account_set_usd_per_cere(usd_per_cere); +// let usd_per_cere = TOKEN / 100; +// set_caller(ctx.provider_id0); +// ctx.contract.account_set_usd_per_cere(usd_per_cere); - let usd_amount = ctx.contract.account_get_usd_per_cere(); - println!("Current usd amount is {}", usd_amount); +// let usd_amount = ctx.contract.account_get_usd_per_cere(); +// println!("Current usd amount is {}", usd_amount); - println!("The current rate is {}", rate); +// println!("The current rate is {}", rate); - let usd_per_kb = rate / KB_PER_GB; - println!("The current rate per kb {}", usd_per_kb); +// let usd_per_kb = rate / KB_PER_GB; +// println!("The current rate per kb {}", usd_per_kb); - let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); - println!("The current cere rate per kb {}", cere_per_kb); +// let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); +// println!("The current cere rate per kb {}", cere_per_kb); - set_caller_value(ctx.provider_id0, 10 * TOKEN); - ctx.contract.account_deposit(); +// set_caller_value(ctx.provider_id0, 10 * TOKEN); +// ctx.contract.account_deposit(); - set_caller(ctx.provider_id0); - ctx.contract.account_bond(5 * TOKEN); +// set_caller(ctx.provider_id0); +// ctx.contract.account_bond(5 * TOKEN); - set_caller(ctx.provider_id0); - ctx.contract.set_fee_bp(1_000); +// set_caller(ctx.provider_id0); +// ctx.contract.set_fee_bp(1_000); - let mut account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); - println!("{:?}", account); +// let mut account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); +// println!("{:?}", account); - ctx.contract.cdn_cluster_put_revenue( - ctx.cluster_id, - vec![(ctx.provider_id0, 1000), (ctx.provider_id0, 541643)], - vec![(ctx.node_id0, 1000), (ctx.node_id1, 541643)], - vec![], - 5, - ); - account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); - println!("{:?}", account); - - let cdn_cluster_list_one = ctx.contract.cdn_cluster_list(0, 10, None); - print!("Cluster list one {:?}", cdn_cluster_list_one); - let node0 = ctx.contract.cdn_nodes.get(ctx.node_id0).unwrap(); - let node1 = ctx.contract.cdn_nodes.get(ctx.node_id1).unwrap(); - - println!("Node 1 {:?}", node0); - println!("Node 2 {:?}", node1); - // let cdn_cluster0 = ctx.contract.cdn_clusters.get(ctx.cluster_id); - // print!("{:?}", cdn_cluster0); - // let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); - // print!("{:?}", cdn_cluster0); - // print!("{:?}", cdn_cluster_list); - - let validated_commit_node0 = ctx.contract.get_validated_commit(ctx.node_id0); - print!("Validated commit {:?}", validated_commit_node0); - - let fee = ctx.contract.get_fee_bp(); - print!("Protocol fee in basis points {:?}", fee); - - let protocol_revenues = ctx.contract.get_protocol_revenues(); - print!("Protocol revenues are {:?}", protocol_revenues); - - set_caller(ctx.provider_id0); - ctx.contract.cdn_cluster_distribute_revenues(0); - - let node0 = ctx.contract.cdn_nodes.get(ctx.node_id0).unwrap(); - let node1 = ctx.contract.cdn_nodes.get(ctx.node_id1).unwrap(); - println!("{:?}", node0); - println!("{:?}", node1); - - let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); - print!("{:?}", cdn_cluster_list); - - account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); - // let node0 = ctx.contract.cdn_nodes.get(ctx.node_id0).unwrap(); - // let node1 = ctx.contract.cdn_nodes.get(ctx.node_id1).unwrap(); - println!("{:?}", account); - // let account1 = ctx.contract.accounts.get(&ctx.provider_id1).unwrap(); - // println!("{:?}", account1); - // let account_balance = ink_env::balance(&ctx.provider_id0); - // println!("{:?}", account_balance); -} +// ctx.contract.cdn_cluster_put_revenue( +// ctx.cluster_id, +// vec![(ctx.provider_id0, 1000), (ctx.provider_id0, 541643)], +// vec![(ctx.node_key0, 1000), (ctx.node_key1, 541643)], +// vec![], +// 5, +// ); +// account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); +// println!("{:?}", account); + +// let cdn_cluster_list_one = ctx.contract.cdn_cluster_list(0, 10, None); +// print!("Cluster list one {:?}", cdn_cluster_list_one); +// let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); +// let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); + +// println!("Node 1 {:?}", node0); +// println!("Node 2 {:?}", node1); +// // let cdn_cluster0 = ctx.contract.cdn_clusters.get(ctx.cluster_id); +// // print!("{:?}", cdn_cluster0); +// // let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); +// // print!("{:?}", cdn_cluster0); +// // print!("{:?}", cdn_cluster_list); + +// let validated_commit_node0 = ctx.contract.get_validated_commit(ctx.node_key0); +// print!("Validated commit {:?}", validated_commit_node0); + +// let fee = ctx.contract.get_fee_bp(); +// print!("Protocol fee in basis points {:?}", fee); + +// let protocol_revenues = ctx.contract.get_protocol_revenues(); +// print!("Protocol revenues are {:?}", protocol_revenues); + +// set_caller(ctx.provider_id0); +// ctx.contract.cdn_cluster_distribute_revenues(0); + +// let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); +// let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); +// println!("{:?}", node0); +// println!("{:?}", node1); + +// let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); +// print!("{:?}", cdn_cluster_list); + +// account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); +// // let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); +// // let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); +// println!("{:?}", account); +// // let account1 = ctx.contract.accounts.get(&ctx.provider_id1).unwrap(); +// // println!("{:?}", account1); +// // let account_balance = ink_env::balance(&ctx.provider_id0); +// // println!("{:?}", account_balance); +// } fn bucket_settle_payment(ctx: &mut TestCluster, test_bucket: &TestBucket) { // Go to the future when some revenues are due. @@ -780,11 +807,11 @@ fn cluster_add_node() { set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); let new_node_id = ctx.contract.node_create( + AccountId::from([0x0d; 32]), rent_per_month, node_params.to_string(), capacity, node_tag, - ctx.manager, ); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); @@ -794,21 +821,21 @@ fn cluster_add_node() { GrantPermission { account_id: ctx.manager, permission: Permission::ManagerTrustedBy(new_provider_id) }) ); - let mut node_ids = Vec::::new(); - node_ids.push(ctx.node_id0); - node_ids.push(ctx.node_id1); - node_ids.push(ctx.node_id2); - node_ids.push(new_node_id); + let mut node_keys = Vec::::new(); + node_keys.push(ctx.node_key0); + node_keys.push(ctx.node_key1); + node_keys.push(ctx.node_key2); + node_keys.push(new_node_id); let mut v_nodes = ctx.vnodes_wrapper.clone(); v_nodes.push(vec![10, 11, 12]); set_caller_value(ctx.manager, CONTRACT_FEE_LIMIT); ctx.contract - .cluster_add_node(ctx.cluster_id, node_ids.clone(), v_nodes.clone()); + .cluster_add_node(ctx.cluster_id, node_keys.clone(), v_nodes.clone()); let cluster_status = ctx.contract.cluster_get(ctx.cluster_id).unwrap(); - assert!(matches!(cluster_status.clone().cluster.node_ids.len(), 4)); + assert!(matches!(cluster_status.clone().cluster.node_keys.len(), 4)); assert!(matches!(cluster_status.clone().cluster.v_nodes.len(), 4)); } @@ -946,7 +973,7 @@ fn bucket_reserve_0_works() { resource_used: 0, revenues: Cash(0), total_rent: 0, - node_ids: vec![] + node_keys: vec![] }, params: "".to_string(), }], @@ -958,15 +985,14 @@ fn bucket_reserve_0_works() { contract.node_list(0, 10, None), ( vec![NodeStatus { - node_id: 0, + node_key: AccountId::default(), node: Node { provider_id: AccountId::default(), rent_per_month: 0, free_resource: 0, node_tag: NodeTag::ACTIVE, - node_pub_key: AccountId::default(), - }, - params: "".to_string(), + node_params: "".to_string(), + } }], 1 ) @@ -1103,11 +1129,11 @@ fn node_change_params_works() { // Change params. set_caller_value(ctx.provider_id0, CONTRACT_FEE_LIMIT); ctx.contract - .node_change_params(ctx.node_id0, "new params".to_string()); + .node_change_params(ctx.node_key0, "new params".to_string()); // Check the changed params. - let status = ctx.contract.node_get(ctx.node_id0)?; - assert_eq!(status.params, "new params"); + let status = ctx.contract.node_get(ctx.node_key0)?; + assert_eq!(status.node.node_params, "new params"); } #[ink::test] @@ -1118,7 +1144,7 @@ fn node_change_params_only_owner() { // Change params. set_caller_value(get_accounts().bob, CONTRACT_FEE_LIMIT); ctx.contract - .node_change_params(ctx.node_id0, "new params".to_string()); + .node_change_params(ctx.node_key0, "new params".to_string()); // Panic. } @@ -1280,52 +1306,50 @@ fn node_list_works() { let node_params1 = "{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"; let capacity = 100; set_caller_value(owner_id1, CONTRACT_FEE_LIMIT); - let node_id1 = ddc_bucket.node_create( + let node_key1 = ddc_bucket.node_create( + AccountId::from([0x0b; 32]), rent_per_month, node_params1.to_string(), capacity, NodeTag::ADDING, - owner_id1, ); let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; set_caller_value(owner_id2, CONTRACT_FEE_LIMIT); - let node_id2 = ddc_bucket.node_create( + let node_key2 = ddc_bucket.node_create( + AccountId::from([0x0c; 32]), rent_per_month, node_params2.to_string(), capacity, NodeTag::ADDING, - owner_id2, ); - let node_status = ddc_bucket.node_get_by_pubkey(owner_id1).unwrap(); + let node_status = ddc_bucket.node_get(AccountId::from([0x0b; 32])).unwrap(); assert_eq!(owner_id1, node_status.node.provider_id.clone()); - assert_ne!(node_id1, node_id2); + assert_ne!(node_key1, node_key2); let count = 3; let node1 = NodeStatus { - node_id: node_id1, + node_key: node_key1, node: Node { provider_id: owner_id1, rent_per_month, free_resource: capacity, node_tag: NodeTag::ADDING, - node_pub_key: owner_id1, + node_params: node_params1.to_string(), }, - params: node_params1.to_string(), }; let node2 = NodeStatus { - node_id: node_id2, + node_key: node_key2, node: Node { provider_id: owner_id2, rent_per_month, free_resource: capacity, node_tag: NodeTag::ADDING, - node_pub_key: owner_id2, + node_params: node_params2.to_string(), }, - params: node_params2.to_string(), }; assert_eq!( diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index 8180c1c3..34d14c42 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -4,13 +4,13 @@ use ink_storage::Mapping; use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; use crate::ddc_bucket::cluster::entity::ClusterId; -use crate::ddc_bucket::node::entity::Node; +use crate::ddc_bucket::node::entity::{Node, NodeKey}; use crate::ddc_bucket::Error::UnknownNode; -use crate::ddc_bucket::{Balance, NodeId, Result}; +use crate::ddc_bucket::{Balance, Result, AccountId}; #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(StorageLayout, Debug,))] -pub struct TopologyStore(Mapping<(ClusterId, u64), NodeId>); +pub struct TopologyStore(Mapping<(ClusterId, u64), NodeKey>); impl TopologyStore { @@ -18,20 +18,20 @@ impl TopologyStore { &mut self, cluster_id: ClusterId, v_nodes: Vec>, - nodes: Vec<(NodeId, &Node)>, + nodes: Vec<(NodeKey, Node)>, ) -> Result { let mut total_rent = 0u128; - let mut vnodes_wrapper_index = 0; + let mut vnodes_idx = 0; for node in &nodes { - let v_nodes_for_node = &v_nodes[vnodes_wrapper_index as usize]; - for v_node in v_nodes_for_node.iter() { + let v_nodes_per_phys_node = &v_nodes[vnodes_idx as usize]; + for v_node in v_nodes_per_phys_node.iter() { self.0.insert((cluster_id, *v_node), &(node.0)); total_rent += node.1.rent_per_month as Balance; } - vnodes_wrapper_index += 1; + vnodes_idx += 1; } Ok(total_rent) @@ -41,11 +41,11 @@ impl TopologyStore { &mut self, cluster_id: u32, v_nodes: Vec, - new_node_id: NodeId, + new_node_key: NodeKey, ) -> Result<()> { for v_node in v_nodes { if self.0.contains(&(cluster_id, v_node)) { - self.0.insert(&(cluster_id, v_node), &new_node_id); + self.0.insert(&(cluster_id, v_node), &new_node_key); } else { return Err(UnknownNode) } @@ -59,11 +59,11 @@ impl TopologyStore { cluster_id: u32, old_v_nodes: &Vec, v_nodes: &Vec>, - nodes: Vec<(NodeId, &Node)>, + nodes: Vec<(NodeKey, Node)>, ) -> Result { // remove old nodes from topology for &old_v_node in old_v_nodes { - self.0.insert((cluster_id, old_v_node), &0); + self.0.insert((cluster_id, old_v_node), &AccountId::default()); // TODO: must be revised } let mut total_rent = 0u32; @@ -71,9 +71,9 @@ impl TopologyStore { // reassign v_nodes to physical ones for node in nodes { - let v_nodes_for_node = &v_nodes[index as usize]; + let v_nodes_per_phys_node = &v_nodes[index as usize]; - for v_node in v_nodes_for_node.iter() { + for v_node in v_nodes_per_phys_node.iter() { self.0.insert((cluster_id, *v_node), &(node.0)); total_rent += node.1.rent_per_month as u32; @@ -85,11 +85,11 @@ impl TopologyStore { Ok(total_rent) } - pub fn get(&self, cluster_id: ClusterId, v_node: u64) -> Result { + pub fn get(&self, cluster_id: ClusterId, v_node: u64) -> Result { self.0.get((cluster_id, v_node)).ok_or(UnknownNode) } - pub fn save(&mut self, cluster_id: ClusterId, v_node: u64, node_id: NodeId) { + pub fn save(&mut self, cluster_id: ClusterId, v_node: u64, node_id: NodeKey) { self.0.insert(&(cluster_id, v_node), &node_id) } } diff --git a/bucket/lib.rs b/bucket/lib.rs index bddc64b0..eeaaad27 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -31,7 +31,7 @@ pub mod ddc_bucket { use self::buckets_perms::store::BucketsPermsStore; use self::cdn_cluster::store::CdnClusterStore; - use self::cdn_node::entity::CdnNodeStatus; + use self::cdn_node::entity::{CdnNodeStatus, NodeId}; use self::protocol::store::ProtocolStore; use self::topology::store::TopologyStore; @@ -68,7 +68,6 @@ pub mod ddc_bucket { cdn_nodes: CdnNodeStore, cdn_node_params: ParamsStore, nodes: NodeStore, - node_params: ParamsStore, accounts: AccountStore, perms: PermStore, network_fee: NetworkFeeStore, @@ -102,20 +101,20 @@ pub mod ddc_bucket { let _ = contract .nodes .create( + AccountId::default(), AccountId::default(), 0, + "".to_string(), 0, NodeTag::ACTIVE, - AccountId::default(), ) .unwrap(); - let _ = contract.node_params.create("".to_string()).unwrap(); let _ = contract .clusters .create( AccountId::default(), &Vec::>::new(), - &Vec::::new(), + &Vec::::new(), ) .unwrap(); let _ = contract.cluster_params.create("".to_string()).unwrap(); @@ -335,7 +334,7 @@ pub mod ddc_bucket { #[ink(topic)] cluster_id: ClusterId, #[ink(topic)] - node_id: NodeId, + node_key: NodeKey, } /// Some resources were reserved for the cluster from the nodes. @@ -365,10 +364,10 @@ pub mod ddc_bucket { pub fn cluster_remove_node( &mut self, cluster_id: ClusterId, - node_ids: Vec, + node_keys: Vec, v_nodes: Vec>, ) { - self.message_cluster_add_node(cluster_id, node_ids, v_nodes) + self.message_cluster_add_node(cluster_id, node_keys, v_nodes) .unwrap() } @@ -379,10 +378,10 @@ pub mod ddc_bucket { pub fn cluster_add_node( &mut self, cluster_id: ClusterId, - node_ids: Vec, + node_keys: Vec, v_nodes: Vec>, ) { - self.message_cluster_add_node(cluster_id, node_ids, v_nodes) + self.message_cluster_add_node(cluster_id, node_keys, v_nodes) .unwrap() } @@ -398,10 +397,10 @@ pub mod ddc_bucket { &mut self, _unused: AccountId, v_nodes: Vec>, - node_ids: Vec, + node_keys: Vec, cluster_params: ClusterParams, ) -> ClusterId { - self.message_cluster_create(v_nodes, node_ids, cluster_params) + self.message_cluster_create(v_nodes, node_keys, cluster_params) .unwrap() } @@ -416,8 +415,8 @@ pub mod ddc_bucket { /// As manager, change a node tag #[ink(message)] - pub fn cluster_change_node_tag(&mut self, node_id: NodeId, new_tag: NodeTag) -> () { - self.message_node_change_tag(node_id, new_tag).unwrap() + pub fn cluster_change_node_tag(&mut self, node_key: NodeKey, new_tag: NodeTag) -> () { + self.message_node_change_tag(node_key, new_tag).unwrap() } /// As manager, re-assign a vnode to another physical node. @@ -428,9 +427,9 @@ pub mod ddc_bucket { &mut self, cluster_id: ClusterId, v_nodes: Vec, - new_node_id: NodeId, + new_node_key: NodeKey, ) -> () { - self.message_cluster_replace_node(cluster_id, v_nodes, new_node_id) + self.message_cluster_replace_node(cluster_id, v_nodes, new_node_key) .unwrap() } @@ -709,7 +708,7 @@ pub mod ddc_bucket { #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] pub struct NodeCreated { #[ink(topic)] - node_id: NodeId, + node_key: NodeKey, #[ink(topic)] provider_id: AccountId, rent_per_month: Balance, @@ -737,13 +736,13 @@ pub mod ddc_bucket { #[ink(message, payable)] pub fn node_create( &mut self, + node_key: NodeKey, rent_per_month: Balance, node_params: NodeParams, capacity: Resource, node_tag: NodeTag, - pubkey: AccountId, - ) -> NodeId { - self.message_node_create(rent_per_month, node_params, capacity, node_tag, pubkey) + ) -> NodeKey { + self.message_node_create(node_key, rent_per_month, node_params, capacity, node_tag) .unwrap() } @@ -751,20 +750,14 @@ pub mod ddc_bucket { /// /// See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema) #[ink(message, payable)] - pub fn node_change_params(&mut self, node_id: NodeId, params: NodeParams) { - self.message_node_change_params(node_id, params).unwrap(); + pub fn node_change_params(&mut self, node_key: NodeKey, params: NodeParams) { + self.message_node_change_params(node_key, params).unwrap(); } /// Get the current status of a node. #[ink(message)] - pub fn node_get(&self, node_id: NodeId) -> Result { - self.message_node_get(node_id) - } - - /// Get the current status of a node by a public key. - #[ink(message)] - pub fn node_get_by_pubkey(&self, pubkey: AccountId) -> Result { - self.message_node_get_by_pub_key(pubkey) + pub fn node_get(&self, node_key: NodeKey) -> Result { + self.message_node_get(node_key) } /// Iterate through all nodes. @@ -789,8 +782,8 @@ pub mod ddc_bucket { /// /// The underlying algorithm swaps the moved to be removed with the last one added, hence the id of the last one added will be updated #[ink(message)] - pub fn node_remove(&mut self, node_id: NodeId) -> Result<()> { - self.message_remove_node(node_id) + pub fn node_remove(&mut self, node_key: NodeKey) -> Result<()> { + self.message_remove_node(node_key) } } // ---- End Node ---- diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index b8a1dc70..d246728f 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -1,6 +1,6 @@ { "source": { - "hash": "0x89bcf7ab14df699f511b76c97cec6ab5b79f0bb690424523f14711a59159c7f6", + "hash": "0x18503c5dfa90d2550281e403227f06fa25d25cb370f0bc19b9652aed48e0a2dc", "language": "ink! 3.4.0", "compiler": "rustc 1.69.0-nightly" }, @@ -218,12 +218,12 @@ { "docs": [], "indexed": true, - "label": "node_id", + "label": "node_key", "type": { "displayName": [ - "NodeId" + "NodeKey" ], - "type": 5 + "type": 2 } } ], @@ -398,12 +398,12 @@ { "docs": [], "indexed": true, - "label": "node_id", + "label": "node_key", "type": { "displayName": [ - "NodeId" + "NodeKey" ], - "type": 5 + "type": 2 } }, { @@ -496,7 +496,7 @@ "displayName": [ "Permission" ], - "type": 77 + "type": 78 } } ], @@ -526,7 +526,7 @@ "displayName": [ "Permission" ], - "type": 77 + "type": 78 } } ], @@ -1073,12 +1073,12 @@ } }, { - "label": "node_ids", + "label": "node_keys", "type": { "displayName": [ "Vec" ], - "type": 18 + "type": 11 } }, { @@ -1087,7 +1087,7 @@ "displayName": [ "Vec" ], - "type": 19 + "type": 18 } } ], @@ -1114,12 +1114,12 @@ } }, { - "label": "node_ids", + "label": "node_keys", "type": { "displayName": [ "Vec" ], - "type": 18 + "type": 11 } }, { @@ -1128,7 +1128,7 @@ "displayName": [ "Vec" ], - "type": 19 + "type": 18 } } ], @@ -1160,16 +1160,16 @@ "displayName": [ "Vec" ], - "type": 19 + "type": 18 } }, { - "label": "node_ids", + "label": "node_keys", "type": { "displayName": [ "Vec" ], - "type": 18 + "type": 11 } }, { @@ -1240,12 +1240,12 @@ { "args": [ { - "label": "node_id", + "label": "node_key", "type": { "displayName": [ - "NodeId" + "NodeKey" ], - "type": 5 + "type": 2 } }, { @@ -1287,16 +1287,16 @@ "displayName": [ "Vec" ], - "type": 20 + "type": 19 } }, { - "label": "new_node_id", + "label": "new_node_key", "type": { "displayName": [ - "NodeId" + "NodeKey" ], - "type": 5 + "type": 2 } } ], @@ -1448,7 +1448,7 @@ "displayName": [ "Vec" ], - "type": 18 + "type": 23 } } ], @@ -1573,7 +1573,7 @@ "displayName": [ "u64" ], - "type": 21 + "type": 20 } } ], @@ -1888,6 +1888,15 @@ ], "type": 14 } + }, + { + "label": "pubkey", + "type": { + "displayName": [ + "AccountId" + ], + "type": 2 + } } ], "docs": [ @@ -1966,6 +1975,32 @@ }, "selector": "0xf9a5a813" }, + { + "args": [ + { + "label": "pubkey", + "type": { + "displayName": [ + "AccountId" + ], + "type": 2 + } + } + ], + "docs": [ + " Get the current state of a cdn node by a public key." + ], + "label": "cdn_node_get_by_pubkey", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 68 + }, + "selector": "0x17d7ffe8" + }, { "args": [ { @@ -2013,6 +2048,36 @@ }, "selector": "0xf8589aae" }, + { + "args": [ + { + "label": "node_id", + "type": { + "displayName": [ + "NodeId" + ], + "type": 5 + } + } + ], + "docs": [ + " Remove cdn node by id ", + " ", + " Only the provider of the node can remove the node (not related to the public key)", + " ", + " The underlying algorithm swaps the moved to be removed with the last one added, hence the id of the last one added will be updated" + ], + "label": "cdn_node_remove", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 72 + }, + "selector": "0xe068fb34" + }, { "args": [ { @@ -2057,6 +2122,15 @@ }, { "args": [ + { + "label": "node_key", + "type": { + "displayName": [ + "NodeKey" + ], + "type": 2 + } + }, { "label": "rent_per_month", "type": { @@ -2092,15 +2166,6 @@ ], "type": 29 } - }, - { - "label": "pubkey", - "type": { - "displayName": [ - "AccountId" - ], - "type": 2 - } } ], "docs": [ @@ -2115,21 +2180,21 @@ "payable": true, "returnType": { "displayName": [ - "NodeId" + "NodeKey" ], - "type": 5 + "type": 2 }, "selector": "0xb77ac1bb" }, { "args": [ { - "label": "node_id", + "label": "node_key", "type": { "displayName": [ - "NodeId" + "NodeKey" ], - "type": 5 + "type": 2 } }, { @@ -2156,12 +2221,12 @@ { "args": [ { - "label": "node_id", + "label": "node_key", "type": { "displayName": [ - "NodeId" + "NodeKey" ], - "type": 5 + "type": 2 } } ], @@ -2175,36 +2240,10 @@ "displayName": [ "Result" ], - "type": 72 + "type": 73 }, "selector": "0x847f3997" }, - { - "args": [ - { - "label": "pubkey", - "type": { - "displayName": [ - "AccountId" - ], - "type": 2 - } - } - ], - "docs": [ - " Get the current status of a node by a public key." - ], - "label": "node_get_by_pubkey", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 72 - }, - "selector": "0x7f6c82d4" - }, { "args": [ { @@ -2248,10 +2287,40 @@ "payable": false, "returnType": { "displayName": [], - "type": 74 + "type": 75 }, "selector": "0x423286d6" }, + { + "args": [ + { + "label": "node_key", + "type": { + "displayName": [ + "NodeKey" + ], + "type": 2 + } + } + ], + "docs": [ + " Remove node by id ", + " ", + " Only the provider of the node can remove the node (not related to the public key)", + " ", + " The underlying algorithm swaps the moved to be removed with the last one added, hence the id of the last one added will be updated" + ], + "label": "node_remove", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 72 + }, + "selector": "0x42e5f273" + }, { "args": [], "docs": [ @@ -2433,7 +2502,7 @@ "displayName": [ "Result" ], - "type": 76 + "type": 77 }, "selector": "0x1d4220fa" }, @@ -2493,7 +2562,7 @@ "displayName": [ "Permission" ], - "type": 77 + "type": 78 } } ], @@ -2529,7 +2598,7 @@ "displayName": [ "Permission" ], - "type": 77 + "type": 78 } } ], @@ -2559,7 +2628,7 @@ "displayName": [ "Permission" ], - "type": 77 + "type": 78 } } ], @@ -2603,7 +2672,7 @@ "displayName": [ "FeeConfig" ], - "type": 78 + "type": 79 } } ], @@ -2726,7 +2795,7 @@ "layout": { "cell": { "key": "0x0500000000000000000000000000000000000000000000000000000000000000", - "ty": 22 + "ty": 21 } }, "name": null @@ -2765,7 +2834,16 @@ "ty": 24 } }, - "name": null + "name": "pub_key_to_node" + }, + { + "layout": { + "cell": { + "key": "0x0800000000000000000000000000000000000000000000000000000000000000", + "ty": 25 + } + }, + "name": "cdn_nodes" } ] } @@ -2779,7 +2857,7 @@ { "layout": { "cell": { - "key": "0x0800000000000000000000000000000000000000000000000000000000000000", + "key": "0x0900000000000000000000000000000000000000000000000000000000000000", "ty": 13 } }, @@ -2794,15 +2872,6 @@ "layout": { "struct": { "fields": [ - { - "layout": { - "cell": { - "key": "0x0900000000000000000000000000000000000000000000000000000000000000", - "ty": 26 - } - }, - "name": "account_node" - }, { "layout": { "cell": { @@ -2811,29 +2880,20 @@ } }, "name": "nodes" - } - ] - } - }, - "name": "nodes" - }, - { - "layout": { - "struct": { - "fields": [ + }, { "layout": { "cell": { "key": "0x0b00000000000000000000000000000000000000000000000000000000000000", - "ty": 13 + "ty": 11 } }, - "name": null + "name": "keys" } ] } }, - "name": "node_params" + "name": "nodes" }, { "layout": { @@ -2982,7 +3042,7 @@ "layout": { "cell": { "key": "0x1600000000000000000000000000000000000000000000000000000000000000", - "ty": 21 + "ty": 20 } }, "name": "start" @@ -2991,7 +3051,7 @@ "layout": { "cell": { "key": "0x1700000000000000000000000000000000000000000000000000000000000000", - "ty": 21 + "ty": 20 } }, "name": "interval" @@ -3000,7 +3060,7 @@ "layout": { "cell": { "key": "0x1800000000000000000000000000000000000000000000000000000000000000", - "ty": 21 + "ty": 20 } }, "name": "commit_duration" @@ -3009,7 +3069,7 @@ "layout": { "cell": { "key": "0x1900000000000000000000000000000000000000000000000000000000000000", - "ty": 21 + "ty": 20 } }, "name": "validation_duration" @@ -3382,13 +3442,13 @@ "typeName": "Cash" }, { - "name": "node_ids", - "type": 18, - "typeName": "Vec" + "name": "node_keys", + "type": 11, + "typeName": "Vec" }, { "name": "v_nodes", - "type": 19, + "type": 18, "typeName": "Vec>" }, { @@ -3435,7 +3495,7 @@ "type": { "def": { "sequence": { - "type": 5 + "type": 19 } } } @@ -3452,16 +3512,6 @@ }, { "id": 20, - "type": { - "def": { - "sequence": { - "type": 21 - } - } - } - }, - { - "id": 21, "type": { "def": { "primitive": "u64" @@ -3469,17 +3519,17 @@ } }, { - "id": 22, + "id": 21, "type": { "def": { "sequence": { - "type": 23 + "type": 22 } } } }, { - "id": 23, + "id": 22, "type": { "def": { "composite": { @@ -3491,7 +3541,7 @@ }, { "name": "cdn_nodes", - "type": 18, + "type": 23, "typeName": "Vec" }, { @@ -3522,17 +3572,59 @@ } }, { - "id": 24, + "id": 23, "type": { "def": { "sequence": { - "type": 25 + "type": 5 } } } }, + { + "id": 24, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "offset_key", + "type": 12, + "typeName": "Key" + } + ] + } + }, + "params": [ + { + "name": "K", + "type": 2 + }, + { + "name": "V", + "type": 5 + } + ], + "path": [ + "ink_storage", + "lazy", + "mapping", + "Mapping" + ] + } + }, { "id": 25, + "type": { + "def": { + "sequence": { + "type": 26 + } + } + } + }, + { + "id": 26, "type": { "def": { "composite": { @@ -3546,6 +3638,11 @@ "name": "undistributed_payment", "type": 8, "typeName": "Balance" + }, + { + "name": "node_pub_key", + "type": 2, + "typeName": "CdnNodePublicKey" } ] } @@ -3560,7 +3657,7 @@ } }, { - "id": 26, + "id": 27, "type": { "def": { "composite": { @@ -3580,7 +3677,7 @@ }, { "name": "V", - "type": 5 + "type": 28 } ], "path": [ @@ -3591,16 +3688,6 @@ ] } }, - { - "id": 27, - "type": { - "def": { - "sequence": { - "type": 28 - } - } - } - }, { "id": 28, "type": { @@ -3626,6 +3713,11 @@ "name": "node_tag", "type": 29, "typeName": "NodeTag" + }, + { + "name": "node_params", + "type": 14, + "typeName": "NodeParams" } ] } @@ -3737,7 +3829,7 @@ }, { "name": "unbonded_timestamp", - "type": 21, + "type": 20, "typeName": "u64" }, { @@ -3870,12 +3962,12 @@ }, { "name": "from_timestamp", - "type": 21, + "type": 20, "typeName": "u64" }, { "name": "to_timestamp", - "type": 21, + "type": 20, "typeName": "u64" } ] @@ -3947,8 +4039,8 @@ "type": { "def": { "tuple": [ - 21, - 21 + 20, + 20 ] } } @@ -3974,7 +4066,7 @@ }, { "name": "V", - "type": 5 + "type": 2 } ], "path": [ @@ -3991,7 +4083,7 @@ "def": { "tuple": [ 5, - 21 + 20 ] } } @@ -4112,7 +4204,7 @@ }, { "name": "rent_covered_until_ms", - "type": 21, + "type": 20, "typeName": "u64" } ] @@ -4505,7 +4597,7 @@ }, { "name": "cluster", - "type": 23, + "type": 22, "typeName": "CdnCluster" } ] @@ -4549,22 +4641,22 @@ "fields": [ { "name": "start", - "type": 21, + "type": 20, "typeName": "u64" }, { "name": "interval", - "type": 21, + "type": 20, "typeName": "u64" }, { "name": "commit_duration", - "type": 21, + "type": 20, "typeName": "u64" }, { "name": "validation_duration", - "type": 21, + "type": 20, "typeName": "u64" } ] @@ -4587,7 +4679,7 @@ "fields": [ { "name": "current_era", - "type": 21, + "type": 20, "typeName": "u64" }, { @@ -4597,17 +4689,17 @@ }, { "name": "previous_era", - "type": 21, + "type": 20, "typeName": "u64" }, { "name": "prev_era_from_timestamp", - "type": 21, + "type": 20, "typeName": "u64" }, { "name": "prev_era_to_timestamp", - "type": 21, + "type": 20, "typeName": "u64" } ] @@ -4707,7 +4799,7 @@ }, { "name": "node", - "type": 25, + "type": 26, "typeName": "CdnNode" }, { @@ -4757,7 +4849,7 @@ { "fields": [ { - "type": 73 + "type": 44 } ], "index": 0, @@ -4778,7 +4870,7 @@ "params": [ { "name": "T", - "type": 73 + "type": 44 }, { "name": "E", @@ -4792,24 +4884,61 @@ }, { "id": 73, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 74 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 48 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 74 + }, + { + "name": "E", + "type": 48 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 74, "type": { "def": { "composite": { "fields": [ { - "name": "node_id", - "type": 5, - "typeName": "NodeId" + "name": "node_key", + "type": 2, + "typeName": "NodeKey" }, { "name": "node", "type": 28, "typeName": "Node" - }, - { - "name": "params", - "type": 14, - "typeName": "Params" } ] } @@ -4824,28 +4953,28 @@ } }, { - "id": 74, + "id": 75, "type": { "def": { "tuple": [ - 75, + 76, 5 ] } } }, { - "id": 75, + "id": 76, "type": { "def": { "sequence": { - "type": 73 + "type": 74 } } } }, { - "id": 76, + "id": 77, "type": { "def": { "variant": { @@ -4887,7 +5016,7 @@ } }, { - "id": 77, + "id": 78, "type": { "def": { "variant": { @@ -4923,7 +5052,7 @@ } }, { - "id": 78, + "id": 79, "type": { "def": { "composite": { From 9a0cb1542d53b76de82473c774d3c71998a6be2e Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Tue, 6 Jun 2023 17:02:10 +0200 Subject: [PATCH 02/89] feat(cdn-nodes): integer id is replaced with external public key --- bucket/ddc_bucket/cdn_cluster/entity.rs | 6 +- bucket/ddc_bucket/cdn_cluster/messages.rs | 59 ++- bucket/ddc_bucket/cdn_cluster/store.rs | 6 +- bucket/ddc_bucket/cdn_node/entity.rs | 11 +- bucket/ddc_bucket/cdn_node/messages.rs | 88 ++-- bucket/ddc_bucket/cdn_node/store.rs | 68 +-- bucket/ddc_bucket/cluster/store.rs | 6 +- bucket/ddc_bucket/committer/messages.rs | 12 +- bucket/ddc_bucket/committer/store.rs | 26 +- bucket/ddc_bucket/tests/test_contract.rs | 414 +++++++-------- bucket/lib.rs | 53 +- scripts/sdk/src/abi/ddc_bucket.json | 603 ++++++++++------------ 12 files changed, 650 insertions(+), 702 deletions(-) diff --git a/bucket/ddc_bucket/cdn_cluster/entity.rs b/bucket/ddc_bucket/cdn_cluster/entity.rs index 0c9482ff..f2be37ef 100644 --- a/bucket/ddc_bucket/cdn_cluster/entity.rs +++ b/bucket/ddc_bucket/cdn_cluster/entity.rs @@ -7,7 +7,7 @@ use ink_primitives::Key; use crate::ddc_bucket::{AccountId, Balance, Result}; use crate::ddc_bucket::cash::{Cash, Payable}; use crate::ddc_bucket::Error::{UnauthorizedClusterManager, InsufficientBalance}; -use crate::ddc_bucket::cdn_node::entity::{Resource, NodeId}; +use crate::ddc_bucket::cdn_node::entity::{Resource, CdnNodeKey}; use crate::ddc_bucket::params::store::Params; pub type ClusterId = u32; @@ -19,7 +19,7 @@ pub type VNodeId = (ClusterId, VNodeIndex); #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] pub struct CdnCluster { pub manager_id: AccountId, - pub cdn_nodes: Vec, + pub cdn_nodes: Vec, pub resources_used: Resource, pub revenues: Cash, pub usd_per_gb: Balance, @@ -43,7 +43,7 @@ pub struct CdnClusterStatus { impl CdnCluster { pub fn new( manager_id: AccountId, - cdn_nodes: Vec, + cdn_nodes: Vec, ) -> Self { CdnCluster { manager_id, diff --git a/bucket/ddc_bucket/cdn_cluster/messages.rs b/bucket/ddc_bucket/cdn_cluster/messages.rs index 3abfbf5e..eadba173 100644 --- a/bucket/ddc_bucket/cdn_cluster/messages.rs +++ b/bucket/ddc_bucket/cdn_cluster/messages.rs @@ -7,7 +7,7 @@ use crate::ddc_bucket::{AccountId, Balance, BucketId, CdnClusterCreated, Cluster use crate::ddc_bucket::cash::{Cash, Payable}; use crate::ddc_bucket::cdn_cluster::entity::{CdnCluster, CdnClusterStatus}; use crate::ddc_bucket::Error::{ClusterManagerIsNotTrusted, UnauthorizedClusterManager, InsufficientBalance}; -use crate::ddc_bucket::cdn_node::entity::{CdnNode, NodeId, Resource}; +use crate::ddc_bucket::cdn_node::entity::{CdnNode, CdnNodeKey, Resource}; use crate::ddc_bucket::perm::entity::Permission; use crate::ddc_bucket::perm::store::PermStore; @@ -16,24 +16,26 @@ const KB_PER_GB: Balance = 1_000_000; impl DdcBucket { pub fn message_cdn_cluster_create( &mut self, - cdn_nodes_ids: Vec, + cdn_nodes_keys: Vec, ) -> Result { let manager = Self::env().caller(); - let cdn_nodes = cdn_nodes_ids.clone(); - - let mut nodes = Vec::<(NodeId, &CdnNode)>::new(); - for node_id in cdn_nodes_ids { - let node = self.cdn_nodes.get(node_id)?; - nodes.push((node_id, node)); - + let mut cdn_nodes = Vec::<(CdnNodeKey, CdnNode)>::new(); + for cdn_node_key in &cdn_nodes_keys { + let cdn_node = self.cdn_nodes.get(*cdn_node_key)?; // Verify that the node provider trusts the cluster manager. - Self::only_cdn_trusted_manager(&self.perms, manager, node.provider_id)?; + Self::only_cdn_trusted_manager(&self.perms, manager, cdn_node.provider_id.clone())?; + + cdn_nodes.push((*cdn_node_key, cdn_node)); } - let cluster_id = self.cdn_clusters.create(manager, cdn_nodes)?; + let cluster_id = self.cdn_clusters.create(manager, cdn_nodes_keys)?; + + Self::env().emit_event(CdnClusterCreated { + cluster_id, + manager + }); - Self::env().emit_event(CdnClusterCreated { cluster_id, manager }); Ok(cluster_id) } @@ -55,7 +57,7 @@ impl DdcBucket { } // First payment is for aggregate consumption for account, second is the aggregate payment for the node (u32 for ids) - pub fn message_cdn_cluster_put_revenue(&mut self, cluster_id: ClusterId, aggregates_accounts: Vec<(AccountId, u128)>, aggregates_nodes: Vec<(u32, u128)>, aggregates_buckets: Vec<(BucketId, Resource)>, era: u64) -> Result<()> { + pub fn message_cdn_cluster_put_revenue(&mut self, cluster_id: ClusterId, aggregates_accounts: Vec<(AccountId, u128)>, aggregates_nodes: Vec<(CdnNodeKey, u128)>, aggregates_buckets: Vec<(BucketId, Resource)>, era: u64) -> Result<()> { let cluster = self.cdn_clusters.get_mut(cluster_id)?; // Self::only_cdn_cluster_manager(cluster)?; @@ -86,8 +88,8 @@ impl DdcBucket { let conv = &self.accounts.1; let committer = &mut self.committer_store; - for &(node_id, resources_used) in aggregates_nodes.iter() { - let node = self.cdn_nodes.get_mut(node_id)?; + for &(cdn_node_key, resources_used) in aggregates_nodes.iter() { + let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; let protocol_fee = self.protocol_store.get_fee_bp(); let protocol = &mut self.protocol_store; @@ -97,10 +99,12 @@ impl DdcBucket { let node_payment = payment * (10_000 - protocol_fee) as u128 / 10_000; let protocol_payment = payment - node_payment; - node.put_payment(node_payment); + cdn_node.put_payment(node_payment); + protocol.put_revenues(Cash(protocol_payment)); + self.cdn_nodes.update(cdn_node_key, &cdn_node)?; - committer.set_validated_commit(node_id, era).unwrap(); + committer.set_validated_commit(cdn_node_key, era).unwrap(); cluster_payment += node_payment; } // Add check that two payments should equal? @@ -135,21 +139,26 @@ impl DdcBucket { // First accumulated revenues to distribute. let mut distributed_revenue = 0; - for node_id in &cluster.cdn_nodes { - let node = self.cdn_nodes.get(*node_id)?; - distributed_revenue += node.undistributed_payment; + for cdn_node_key in &cluster.cdn_nodes { + let cdn_node = self.cdn_nodes.get(*cdn_node_key)?; + distributed_revenue += cdn_node.undistributed_payment; } // Charge the provider payments from the cluster. cluster.revenues.pay(Payable(distributed_revenue))?; // Distribute revenues to nodes - for node_id in &cluster.cdn_nodes { - let node = self.cdn_nodes.get_mut(*node_id)?; + for cdn_node_key in &cluster.cdn_nodes { + let mut cdn_node = self.cdn_nodes.get(*cdn_node_key)?; + + Self::send_cash(cdn_node.provider_id, Cash(cdn_node.undistributed_payment))?; + cdn_node.take_payment(cdn_node.undistributed_payment)?; + self.cdn_nodes.update(*cdn_node_key, &cdn_node)?; - Self::send_cash(node.provider_id, Cash(node.undistributed_payment))?; - node.take_payment(node.undistributed_payment)?; - Self::env().emit_event(ClusterDistributeRevenues { cluster_id, provider_id: node.provider_id }); + Self::env().emit_event(ClusterDistributeRevenues { + cluster_id, + provider_id: cdn_node.provider_id + }); } Ok(()) diff --git a/bucket/ddc_bucket/cdn_cluster/store.rs b/bucket/ddc_bucket/cdn_cluster/store.rs index 46188ef6..88f0ece7 100644 --- a/bucket/ddc_bucket/cdn_cluster/store.rs +++ b/bucket/ddc_bucket/cdn_cluster/store.rs @@ -4,7 +4,7 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; use ink_prelude::vec::Vec; use crate::ddc_bucket::{AccountId, Error::*, Result}; -use crate::ddc_bucket::cdn_node::entity::{NodeId}; +use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; use super::entity::{CdnCluster, ClusterId}; pub const MAX_VNODES: u32 = 300; @@ -17,9 +17,9 @@ impl CdnClusterStore { pub fn create( &mut self, manager_id: AccountId, - cdn_nodes: Vec, + cdn_nodes_keys: Vec, ) -> Result { - let cluster = CdnCluster::new(manager_id, cdn_nodes); + let cluster = CdnCluster::new(manager_id, cdn_nodes_keys); let cluster_id: ClusterId = self.0.len().try_into().unwrap(); self.0.push(cluster); diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index 9f337506..515ceb52 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -7,8 +7,8 @@ use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; use crate::ddc_bucket::params::store::Params; pub type ProviderId = AccountId; -pub type NodeId = u32; -pub type CdnNodePublicKey = AccountId; +pub type CdnNodeKey = AccountId; +pub type CdnNodeParams = Params; pub type Resource = u32; #[derive(Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] @@ -16,7 +16,7 @@ pub type Resource = u32; pub struct CdnNode { pub provider_id: ProviderId, pub undistributed_payment: Balance, - pub node_pub_key: CdnNodePublicKey, + pub cdn_node_params: CdnNodeParams, } // https://use.ink/3.x/ink-vs-solidity#nested-mappings--custom--advanced-structures @@ -30,9 +30,8 @@ impl ink_storage::traits::PackedAllocate for CdnNode { #[derive(Clone, PartialEq, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] pub struct CdnNodeStatus { - pub node_id: NodeId, - pub node: CdnNode, - pub params: Params, + pub cdn_node_key: CdnNodeKey, + pub cdn_node: CdnNode, } impl CdnNode { diff --git a/bucket/ddc_bucket/cdn_node/messages.rs b/bucket/ddc_bucket/cdn_node/messages.rs index 28843d9f..735853b6 100644 --- a/bucket/ddc_bucket/cdn_node/messages.rs +++ b/bucket/ddc_bucket/cdn_node/messages.rs @@ -1,13 +1,11 @@ //! The public interface to manage Nodes. -use ink_lang::codegen::StaticEnv; +use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; +use crate::ddc_bucket::{AccountId, DdcBucket, CdnNodeCreated, Result, Balance}; +use crate::ddc_bucket::perm::entity::{Permission}; -use crate::ddc_bucket::{AccountId, DdcBucket, Result}; -use crate::ddc_bucket::params::store::Params; -use crate::ddc_bucket::perm::entity::Permission; - -use super::entity::{NodeId, CdnNodeStatus}; +use super::entity::{CdnNodeKey, CdnNodeStatus, CdnNodeParams}; impl DdcBucket { pub fn message_cdn_node_trust_manager(&mut self, manager: AccountId, is_trusted: bool) -> Result<()> { @@ -16,72 +14,78 @@ impl DdcBucket { self.impl_grant_permission(manager, permission, is_trusted) } - pub fn message_cdn_node_create(&mut self, node_params: Params, pubkey: AccountId) -> Result { + pub fn message_cdn_node_create(&mut self, cdn_node_key: CdnNodeKey, cdn_node_params: CdnNodeParams) -> Result { let provider_id = Self::env().caller(); - let node_id = self.cdn_nodes.create(provider_id, 0, pubkey).unwrap(); - let params_id = self.cdn_node_params.create(node_params.clone())?; - assert_eq!(node_id, params_id); + let undistributed_payment: Balance = 0; + + let cdn_node_key = self + .cdn_nodes + .create(cdn_node_key, provider_id, cdn_node_params.clone(), undistributed_payment) + .unwrap(); - Ok(node_id) + Self::env().emit_event(CdnNodeCreated { + cdn_node_key, + provider_id, + cdn_node_params, + undistributed_payment, + }); + + Ok(cdn_node_key) } - pub fn message_cdn_node_change_params(&mut self, node_id: NodeId, params: Params) -> Result<()> { + pub fn message_cdn_node_change_params(&mut self, cdn_node_key: CdnNodeKey, cdn_node_params: CdnNodeParams) -> Result<()> { let caller = Self::env().caller(); - let node = self.cdn_nodes.get(node_id)?; - node.only_owner(caller)?; - Self::impl_change_params(&mut self.cdn_node_params, node_id, params) + let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; + cdn_node.only_owner(caller)?; + cdn_node.cdn_node_params = cdn_node_params; + self.cdn_nodes.update(cdn_node_key, &cdn_node)?; + + Ok(()) } - pub fn message_cdn_node_get(&self, node_id: NodeId) -> Result { - let node = self.cdn_nodes.get(node_id)?.clone(); - let params = self.cdn_node_params.get(node_id)?.clone(); - Ok(CdnNodeStatus { node_id, node, params }) + pub fn message_cdn_node_get(&self, cdn_node_key: CdnNodeKey) -> Result { + let cdn_node = self.cdn_nodes.get(cdn_node_key)?; + Ok(CdnNodeStatus { + cdn_node_key, + cdn_node, + }) } pub fn message_cdn_node_list(&self, offset: u32, limit: u32, filter_provider_id: Option) -> (Vec, u32) { let mut cdn_nodes = Vec::with_capacity(limit as usize); - for node_id in offset..offset + limit { - let node = match self.cdn_nodes.cdn_nodes.get(node_id as usize) { + for idx in offset..offset + limit { + let cdn_node_key = match self.cdn_nodes.keys.get(idx as usize) { None => break, // No more items, stop. - Some(node) => node, + Some(cdn_node_key) => cdn_node_key.clone(), }; + + let cdn_node = self.cdn_nodes.cdn_nodes.get(cdn_node_key).unwrap(); + // Apply the filter if given. if let Some(provider_id) = filter_provider_id { - if provider_id != node.provider_id { + if provider_id != cdn_node.provider_id { continue; // Skip non-matches. } } // Include the complete status of matched items. let status = CdnNodeStatus { - node_id, - node: node.clone(), - params: self.cdn_node_params.get(node_id).unwrap().clone(), + cdn_node_key, + cdn_node, }; cdn_nodes.push(status); } - (cdn_nodes, self.cdn_nodes.cdn_nodes.len().try_into().unwrap()) - } - pub fn message_cdn_node_get_by_pub_key(&self, pubkey: AccountId) -> Result { - let node_id = self.cdn_nodes.get_by_pub_key(pubkey).unwrap(); - let node = self.cdn_nodes.get(node_id)?.clone(); - let params = self.cdn_node_params.get(node_id)?.clone(); - Ok(CdnNodeStatus { - node_id, - node, - params, - }) + (cdn_nodes, self.cdn_nodes.keys.len().try_into().unwrap()) } - pub fn message_remove_cdn_node(&mut self, node_id: NodeId) -> Result<()> { + pub fn message_remove_cdn_node(&mut self, cdn_node_key: CdnNodeKey) -> Result<()> { let caller = Self::env().caller(); - let node = self.cdn_nodes.get_mut(node_id)?; - node.only_owner(caller)?; - - self.cdn_nodes.remove_node(node_id) + let cdn_node = self.cdn_nodes.get(cdn_node_key)?; + cdn_node.only_owner(caller)?; + self.cdn_nodes.remove(cdn_node_key) } } diff --git a/bucket/ddc_bucket/cdn_node/store.rs b/bucket/ddc_bucket/cdn_node/store.rs index 2a1dc83e..392231b0 100644 --- a/bucket/ddc_bucket/cdn_node/store.rs +++ b/bucket/ddc_bucket/cdn_node/store.rs @@ -1,59 +1,65 @@ //! The store where to create and access Nodes. use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; -use ink_prelude::vec::Vec as InkVec; use ink_storage::Mapping; +use ink_prelude::vec::Vec; use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; +use super::entity::{CdnNode, CdnNodeKey, CdnNodeParams}; -use super::entity::{CdnNode, NodeId}; - -pub type NodeKey = AccountId; #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(StorageLayout, Debug))] pub struct CdnNodeStore { - pub pub_key_to_node: Mapping, - pub cdn_nodes: InkVec + pub cdn_nodes: Mapping, + // This vector is temporal and must be replaced with an offchain indexer + pub keys: Vec } impl CdnNodeStore { pub fn create( &mut self, + cdn_node_key: CdnNodeKey, provider_id: AccountId, + cdn_node_params: CdnNodeParams, undistributed_payment: Balance, - pubkey: AccountId, - ) -> Result { - let node_id: NodeId = self.cdn_nodes.len().try_into().unwrap(); - let node = CdnNode { provider_id, undistributed_payment, node_pub_key: pubkey }; - - let exists = self.pub_key_to_node.contains(&pubkey); - if exists { - return Err(NodeAlreadyExists); + ) -> Result { + + let cdn_node = CdnNode { + provider_id, + cdn_node_params, + undistributed_payment + }; + + if self.cdn_nodes.contains(&cdn_node_key) { + Err(CdnNodeAlreadyExists) + } else { + self.cdn_nodes.insert(&cdn_node_key, &cdn_node); + self.keys.push(cdn_node_key); + Ok(cdn_node_key) } - self.cdn_nodes.push(node); - self.pub_key_to_node.insert(&pubkey, &node_id); - Ok(node_id) } - pub fn get_by_pub_key(&self, pubkey: AccountId) -> Result { - self.pub_key_to_node.get(&pubkey).ok_or(NodeDoesNotExist) -} + pub fn get(&self, cdn_node_key: CdnNodeKey) -> Result { + self.cdn_nodes.get(cdn_node_key).ok_or(CdnNodeDoesNotExist) + } - pub fn get(&self, node_id: NodeId) -> Result<&CdnNode> { - self.cdn_nodes.get(node_id as usize).ok_or(NodeDoesNotExist) + pub fn update(&mut self, cdn_node_key: CdnNodeKey, cdn_node: &CdnNode) -> Result<()> { + if !self.cdn_nodes.contains(&cdn_node_key) { + Err(CdnNodeDoesNotExist) + } else { + self.cdn_nodes.insert(cdn_node_key, cdn_node); + Ok(()) + } } - pub fn get_mut(&mut self, node_id: NodeId) -> Result<&mut CdnNode> { - self.cdn_nodes.get_mut(node_id as usize).ok_or(NodeDoesNotExist) + pub fn remove(&mut self, cdn_node_key: CdnNodeKey) -> Result<()> { + self.cdn_nodes.remove(cdn_node_key); + if let Some(pos) = self.keys.iter().position(|x| *x == cdn_node_key) { + self.keys.remove(pos); + }; + Ok(()) } - pub fn remove_node(&mut self, node_id: NodeId) -> Result<()> { - let total_nodes = self.cdn_nodes.len(); - let last_node = self.cdn_nodes.get(total_nodes - 1).ok_or(NodeDoesNotExist).unwrap(); - self.pub_key_to_node.insert(&last_node.node_pub_key, &node_id); - self.cdn_nodes.swap_remove(node_id.try_into().unwrap()); - Ok(()) -} } diff --git a/bucket/ddc_bucket/cluster/store.rs b/bucket/ddc_bucket/cluster/store.rs index 9f02fd94..2c1da452 100644 --- a/bucket/ddc_bucket/cluster/store.rs +++ b/bucket/ddc_bucket/cluster/store.rs @@ -17,11 +17,11 @@ impl ClusterStore { &mut self, manager_id: AccountId, v_nodes: &Vec>, - node_ids: &Vec, + node_keys: &Vec, ) -> Result { - let cluster = Cluster::new(manager_id, v_nodes, node_ids); + let cluster = Cluster::new(manager_id, v_nodes, node_keys); - let cluster_id: ClusterId = self.0.len().try_into().unwrap(); + let cluster_id: ClusterId = self.0.len().try_into().unwrap(); self.0.push(cluster); Ok(cluster_id) diff --git a/bucket/ddc_bucket/committer/messages.rs b/bucket/ddc_bucket/committer/messages.rs index 349d8e17..38ae02cc 100644 --- a/bucket/ddc_bucket/committer/messages.rs +++ b/bucket/ddc_bucket/committer/messages.rs @@ -2,22 +2,22 @@ use ink_lang::codegen::StaticEnv; use ink_env::Error; use ink_prelude::vec::Vec; -use crate::ddc_bucket::{AccountId, DdcBucket, NodeId}; +use crate::ddc_bucket::{AccountId, DdcBucket, CdnNodeKey}; use super::store::{Commit, EraConfig, EraStatus, EraAndTimestamp}; pub type Result = core::result::Result; impl DdcBucket { - pub fn message_set_commit(&mut self, cdn_owner: AccountId, node_id: NodeId, commit: Commit) { - self.committer_store.set_commit(cdn_owner, node_id, commit); + pub fn message_set_commit(&mut self, cdn_owner: AccountId, cdn_node_key: CdnNodeKey, commit: Commit) { + self.committer_store.set_commit(cdn_owner, cdn_node_key, commit); } - pub fn message_get_commit(&self, cdn_owner: AccountId) -> Vec<(NodeId, Commit)> { + pub fn message_get_commit(&self, cdn_owner: AccountId) -> Vec<(CdnNodeKey, Commit)> { self.committer_store.get_commit(cdn_owner) } - pub fn message_get_validated_commit(&self, node: NodeId) -> EraAndTimestamp { - self.committer_store.get_validate_commit(node) + pub fn message_get_validated_commit(&self, cdn_node_key: CdnNodeKey) -> EraAndTimestamp { + self.committer_store.get_validate_commit(cdn_node_key) } pub fn message_set_era(&mut self, era_config: EraConfig) -> Result<()> { diff --git a/bucket/ddc_bucket/committer/store.rs b/bucket/ddc_bucket/committer/store.rs index 06d5346d..7216e964 100644 --- a/bucket/ddc_bucket/committer/store.rs +++ b/bucket/ddc_bucket/committer/store.rs @@ -1,4 +1,4 @@ -use crate::ddc_bucket::{AccountId, Hash, NodeId}; +use crate::ddc_bucket::{AccountId, Hash, CdnNodeKey}; use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout, PackedLayout}; use ink_prelude::vec::Vec; @@ -52,8 +52,8 @@ pub struct EraConfig { #[cfg_attr(feature = "std", derive(StorageLayout))] pub struct CommitterStore { operator_id: AccountId, - commits: Mapping>, - validated_commits: Mapping, + commits: Mapping>, + validated_commits: Mapping, era_settings: EraConfig } @@ -68,35 +68,35 @@ impl CommitterStore { /// The node can set the latest commit with this function /// check the sender !!!! - pub fn set_commit(&mut self, cdn_owner: AccountId, node_id: NodeId, commit: Commit) { + pub fn set_commit(&mut self, cdn_owner: AccountId, cdn_node_key: CdnNodeKey, commit: Commit) { if !self.commits.contains(&cdn_owner) { - let empty_vec = Vec::<(u32, Commit)>::new(); + let empty_vec = Vec::<(CdnNodeKey, Commit)>::new(); self.commits.insert(cdn_owner, &empty_vec); } let mut account_commits = self.commits.get(&cdn_owner).unwrap(); - let index = account_commits.iter().position(|(node, _)| *node == node_id).unwrap_or(usize::MAX); + let index = account_commits.iter().position(|(node, _)| *node == cdn_node_key).unwrap_or(usize::MAX); if index != usize::MAX { account_commits.remove(index); } - account_commits.push((node_id, commit)); + account_commits.push((cdn_node_key, commit)); self.commits.insert(&cdn_owner, &account_commits); } - pub fn get_commit(&self, cdn_owner: AccountId) -> Vec<(NodeId, Commit)> { - self.commits.get(&cdn_owner).unwrap_or(Vec::<(u32, Commit)>::new()).iter().cloned().collect() + pub fn get_commit(&self, cdn_owner: AccountId) -> Vec<(CdnNodeKey, Commit)> { + self.commits.get(&cdn_owner).unwrap_or(Vec::<(CdnNodeKey, Commit)>::new()).iter().cloned().collect() } // Set the last validated commit per CDN node - pub fn set_validated_commit(&mut self, node: NodeId, era: u64) -> Result<()> { + pub fn set_validated_commit(&mut self, cdn_node_key: CdnNodeKey, era: u64) -> Result<()> { let prev_era_to_timestamp = self.era_settings.start + self.era_settings.interval * (era + 1); - self.validated_commits.insert(&node, &(era, prev_era_to_timestamp)); + self.validated_commits.insert(&cdn_node_key, &(era, prev_era_to_timestamp)); Ok(()) } // Get the last era & timestamp validated per CDN node - pub fn get_validate_commit(&self, node: NodeId) -> EraAndTimestamp { - self.validated_commits.get(&node).unwrap_or((0,0)) + pub fn get_validate_commit(&self, cdn_node_key: CdnNodeKey) -> EraAndTimestamp { + self.validated_commits.get(&cdn_node_key).unwrap_or((0,0)) } // Akin to modifier diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index 3229f8ae..1348699b 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -1,7 +1,7 @@ use ink_lang as ink; use crate::ddc_bucket::account::entity::Account; -use crate::ddc_bucket::cdn_node::entity::NodeId; +// use crate::ddc_bucket::cdn_node::entity::CdnNodeKey; use crate::ddc_bucket::cluster::entity::ClusterStatus; use crate::ddc_bucket::flow::Flow; use crate::ddc_bucket::node::entity::{NodeTag, NodeKey}; @@ -157,108 +157,114 @@ fn new_cluster() -> TestCluster { } } -// fn new_cluster_cdn() -> TestCluster { -// let accounts = get_accounts(); -// set_balance(accounts.charlie, 1000 * TOKEN); -// set_balance(accounts.django, 1000 * TOKEN); -// let provider_id0 = accounts.alice; -// let provider_id1 = accounts.bob; -// let provider_id2 = accounts.charlie; -// let manager = accounts.django; - -// let mut contract = setup(); - -// // Provide a Node. -// let rent_per_vnode: Balance = 10 * TOKEN; -// let node_params0 = "{\"url\":\"https://ddc.cere.network/bucket/{BUCKET_ID}\"}"; -// let capacity = 100; - -// for provider_id in [provider_id0, provider_id1, provider_id2] { -// set_caller_value(provider_id, CONTRACT_FEE_LIMIT); - -// contract.node_trust_manager(manager); -// let expected_perm = Permission::ManagerTrustedBy(provider_id); -// assert!(contract.has_permission(manager, expected_perm)); -// } - -// set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); - -// let node_key0 = contract.cdn_node_create(node_params0.to_string(), provider_id0); - -// // Provide another Node. -// let node_params1 = "{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"; -// set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); - -// let node_key1 = contract.cdn_node_create(node_params1.to_string(), provider_id1); - -// // Provide another Node. -// let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; -// set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); - -// let node_key2 = contract.cdn_node_create(node_params2.to_string(), provider_id2); - -// // Create a Cluster. -// let _cluster_params = "{}"; - -// // TODO: adjust after cdn cluster topology and node addition - -// let vnodes = vec![1, 2, 3, 4, 5, 6]; - -// let node_keys = vec![node_key0, node_key1, node_key2]; -// let mut vnodes_wrapper = Vec::>::new(); -// vnodes_wrapper.push(vnodes); - -// let mut vnodes_wrapper = Vec::>::new(); - -// let vnodes_for_first_node = vec![1, 2, 3]; -// let vnodes_for_second_node = vec![4, 5, 6]; -// let vnodes_for_third_node = vec![7, 8, 9]; - -// vnodes_wrapper.push(vnodes_for_first_node); -// vnodes_wrapper.push(vnodes_for_second_node); -// vnodes_wrapper.push(vnodes_for_third_node); - -// set_caller_value(manager, CONTRACT_FEE_LIMIT); - -// let cluster_id = contract.cdn_cluster_create( -// vec![ -// AccountId::from([0x0a; 32]), -// AccountId::from([0x0b; 32]), -// AccountId::from([0x0c; 32]) -// ] -// ); - -// let reserved = 10; - -// let mut vnodes = Vec::::new(); - -// for v_nodes_vec in vnodes_wrapper.clone() { -// for v_node in v_nodes_vec { -// vnodes.push(v_node.clone()); -// } -// } - -// TestCluster { -// contract, -// manager, -// cluster_id, -// provider_id0, -// provider_id1, -// provider_id2, -// node_key0, -// node_key1, -// node_key2, -// rent_per_vnode, -// vnodes_wrapper, -// node_params0, -// node_params1, -// node_params2, -// capacity, -// reserved, -// node_keys, -// vnodes, -// } -// } +fn new_cluster_cdn() -> TestCluster { + let accounts = get_accounts(); + set_balance(accounts.charlie, 1000 * TOKEN); + set_balance(accounts.django, 1000 * TOKEN); + let provider_id0 = accounts.alice; + let provider_id1 = accounts.bob; + let provider_id2 = accounts.charlie; + let manager = accounts.django; + + let mut contract = setup(); + + // Provide a Node. + let rent_per_vnode: Balance = 10 * TOKEN; + let node_params0 = "{\"url\":\"https://ddc.cere.network/bucket/{BUCKET_ID}\"}"; + let capacity = 100; + + for provider_id in [provider_id0, provider_id1, provider_id2] { + set_caller_value(provider_id, CONTRACT_FEE_LIMIT); + + contract.node_trust_manager(manager); + let expected_perm = Permission::ManagerTrustedBy(provider_id); + assert!(contract.has_permission(manager, expected_perm)); + } + + set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); + + let cdn_node_key0 = AccountId::from([0x0a; 32]); + + let node_key0 = contract.cdn_node_create(cdn_node_key0, node_params0.to_string()); + + // Provide another Node. + let node_params1 = "{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"; + set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); + + let cdn_node_key1 = AccountId::from([0x0b; 32]); + + let node_key1 = contract.cdn_node_create(cdn_node_key1, node_params1.to_string()); + + // Provide another Node. + let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; + set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); + + let cdn_node_key2 = AccountId::from([0x0c; 32]); + + let node_key2 = contract.cdn_node_create(cdn_node_key2, node_params2.to_string()); + + // Create a Cluster. + let _cluster_params = "{}"; + + // TODO: adjust after cdn cluster topology and node addition + + let vnodes = vec![1, 2, 3, 4, 5, 6]; + + let node_keys = vec![node_key0, node_key1, node_key2]; + let mut vnodes_wrapper = Vec::>::new(); + vnodes_wrapper.push(vnodes); + + let mut vnodes_wrapper = Vec::>::new(); + + let vnodes_for_first_node = vec![1, 2, 3]; + let vnodes_for_second_node = vec![4, 5, 6]; + let vnodes_for_third_node = vec![7, 8, 9]; + + vnodes_wrapper.push(vnodes_for_first_node); + vnodes_wrapper.push(vnodes_for_second_node); + vnodes_wrapper.push(vnodes_for_third_node); + + set_caller_value(manager, CONTRACT_FEE_LIMIT); + + let cluster_id = contract.cdn_cluster_create( + vec![ + AccountId::from([0x0a; 32]), + AccountId::from([0x0b; 32]), + AccountId::from([0x0c; 32]) + ] + ); + + let reserved = 10; + + let mut vnodes = Vec::::new(); + + for v_nodes_vec in vnodes_wrapper.clone() { + for v_node in v_nodes_vec { + vnodes.push(v_node.clone()); + } + } + + TestCluster { + contract, + manager, + cluster_id, + provider_id0, + provider_id1, + provider_id2, + node_key0, + node_key1, + node_key2, + rent_per_vnode, + vnodes_wrapper, + node_params0, + node_params1, + node_params2, + capacity, + reserved, + node_keys, + vnodes, + } +} struct TestBucket { bucket_id: BucketId, @@ -573,127 +579,127 @@ fn cluster_management_validation_works() { ); } -// #[ink::test] -// fn cdn_cluster_gas_converter_works() { -// println!("Creating new cdn cluster"); - -// let mut ctx = new_cluster_cdn(); - -// println!("Got cdn cluster back"); -// // The provider stops trusting the manager. -// println!("Cdn cluster id is {}", ctx.cluster_id); -// set_caller(ctx.manager); -// ctx.contract.cdn_set_rate(ctx.cluster_id, 3_750_000_000); -// set_caller(ctx.provider_id0); -// let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); - -// let usd_per_cere = TOKEN / 100; -// set_caller(ctx.provider_id0); -// ctx.contract.account_set_usd_per_cere(usd_per_cere); - -// let usd_amount = ctx.contract.account_get_usd_per_cere(); -// println!("Current usd amount is {}", usd_amount); - -// println!("The current rate is {}", rate); - -// let usd_per_kb = rate / KB_PER_GB; -// println!("The current rate per kb {}", usd_per_kb); - -// let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); -// println!("The current cere rate per kb {}", cere_per_kb); -// } +#[ink::test] +fn cdn_cluster_gas_converter_works() { + println!("Creating new cdn cluster"); -// #[ink::test] -// fn cdn_cluster_payment_works() { -// println!("Creating new cdn cluster"); + let mut ctx = new_cluster_cdn(); -// let mut ctx = new_cluster_cdn(); + println!("Got cdn cluster back"); + // The provider stops trusting the manager. + println!("Cdn cluster id is {}", ctx.cluster_id); + set_caller(ctx.manager); + ctx.contract.cdn_set_rate(ctx.cluster_id, 3_750_000_000); + set_caller(ctx.provider_id0); + let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); -// println!("Got cdn cluster back"); -// // The provider stops trusting the manager. -// println!("Cdn cluster id is {}", ctx.cluster_id); -// set_caller(ctx.provider_id0); -// let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); + let usd_per_cere = TOKEN / 100; + set_caller(ctx.provider_id0); + ctx.contract.account_set_usd_per_cere(usd_per_cere); -// let usd_per_cere = TOKEN / 100; -// set_caller(ctx.provider_id0); -// ctx.contract.account_set_usd_per_cere(usd_per_cere); + let usd_amount = ctx.contract.account_get_usd_per_cere(); + println!("Current usd amount is {}", usd_amount); -// let usd_amount = ctx.contract.account_get_usd_per_cere(); -// println!("Current usd amount is {}", usd_amount); + println!("The current rate is {}", rate); -// println!("The current rate is {}", rate); + let usd_per_kb = rate / KB_PER_GB; + println!("The current rate per kb {}", usd_per_kb); -// let usd_per_kb = rate / KB_PER_GB; -// println!("The current rate per kb {}", usd_per_kb); + let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); + println!("The current cere rate per kb {}", cere_per_kb); +} -// let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); -// println!("The current cere rate per kb {}", cere_per_kb); +#[ink::test] +fn cdn_cluster_payment_works() { + println!("Creating new cdn cluster"); -// set_caller_value(ctx.provider_id0, 10 * TOKEN); -// ctx.contract.account_deposit(); + let mut ctx = new_cluster_cdn(); -// set_caller(ctx.provider_id0); -// ctx.contract.account_bond(5 * TOKEN); + println!("Got cdn cluster back"); + // The provider stops trusting the manager. + println!("Cdn cluster id is {}", ctx.cluster_id); + set_caller(ctx.provider_id0); + let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); -// set_caller(ctx.provider_id0); -// ctx.contract.set_fee_bp(1_000); + let usd_per_cere = TOKEN / 100; + set_caller(ctx.provider_id0); + ctx.contract.account_set_usd_per_cere(usd_per_cere); -// let mut account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); -// println!("{:?}", account); + let usd_amount = ctx.contract.account_get_usd_per_cere(); + println!("Current usd amount is {}", usd_amount); -// ctx.contract.cdn_cluster_put_revenue( -// ctx.cluster_id, -// vec![(ctx.provider_id0, 1000), (ctx.provider_id0, 541643)], -// vec![(ctx.node_key0, 1000), (ctx.node_key1, 541643)], -// vec![], -// 5, -// ); -// account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); -// println!("{:?}", account); + println!("The current rate is {}", rate); -// let cdn_cluster_list_one = ctx.contract.cdn_cluster_list(0, 10, None); -// print!("Cluster list one {:?}", cdn_cluster_list_one); -// let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); -// let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); + let usd_per_kb = rate / KB_PER_GB; + println!("The current rate per kb {}", usd_per_kb); -// println!("Node 1 {:?}", node0); -// println!("Node 2 {:?}", node1); -// // let cdn_cluster0 = ctx.contract.cdn_clusters.get(ctx.cluster_id); -// // print!("{:?}", cdn_cluster0); -// // let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); -// // print!("{:?}", cdn_cluster0); -// // print!("{:?}", cdn_cluster_list); + let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); + println!("The current cere rate per kb {}", cere_per_kb); -// let validated_commit_node0 = ctx.contract.get_validated_commit(ctx.node_key0); -// print!("Validated commit {:?}", validated_commit_node0); + set_caller_value(ctx.provider_id0, 10 * TOKEN); + ctx.contract.account_deposit(); -// let fee = ctx.contract.get_fee_bp(); -// print!("Protocol fee in basis points {:?}", fee); + set_caller(ctx.provider_id0); + ctx.contract.account_bond(5 * TOKEN); -// let protocol_revenues = ctx.contract.get_protocol_revenues(); -// print!("Protocol revenues are {:?}", protocol_revenues); - -// set_caller(ctx.provider_id0); -// ctx.contract.cdn_cluster_distribute_revenues(0); + set_caller(ctx.provider_id0); + ctx.contract.set_fee_bp(1_000); -// let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); -// let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); -// println!("{:?}", node0); -// println!("{:?}", node1); - -// let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); -// print!("{:?}", cdn_cluster_list); + let mut account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); + println!("{:?}", account); -// account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); -// // let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); -// // let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); -// println!("{:?}", account); -// // let account1 = ctx.contract.accounts.get(&ctx.provider_id1).unwrap(); -// // println!("{:?}", account1); -// // let account_balance = ink_env::balance(&ctx.provider_id0); -// // println!("{:?}", account_balance); -// } + ctx.contract.cdn_cluster_put_revenue( + ctx.cluster_id, + vec![(ctx.provider_id0, 1000), (ctx.provider_id0, 541643)], + vec![(ctx.node_key0, 1000), (ctx.node_key1, 541643)], + vec![], + 5, + ); + account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); + println!("{:?}", account); + + let cdn_cluster_list_one = ctx.contract.cdn_cluster_list(0, 10, None); + print!("Cluster list one {:?}", cdn_cluster_list_one); + let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); + let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); + + println!("Node 1 {:?}", node0); + println!("Node 2 {:?}", node1); + // let cdn_cluster0 = ctx.contract.cdn_clusters.get(ctx.cluster_id); + // print!("{:?}", cdn_cluster0); + // let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); + // print!("{:?}", cdn_cluster0); + // print!("{:?}", cdn_cluster_list); + + let validated_commit_node0 = ctx.contract.get_validated_commit(ctx.node_key0); + print!("Validated commit {:?}", validated_commit_node0); + + let fee = ctx.contract.get_fee_bp(); + print!("Protocol fee in basis points {:?}", fee); + + let protocol_revenues = ctx.contract.get_protocol_revenues(); + print!("Protocol revenues are {:?}", protocol_revenues); + + set_caller(ctx.provider_id0); + ctx.contract.cdn_cluster_distribute_revenues(0); + + let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); + let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); + println!("{:?}", node0); + println!("{:?}", node1); + + let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); + print!("{:?}", cdn_cluster_list); + + account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); + // let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); + // let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); + println!("{:?}", account); + // let account1 = ctx.contract.accounts.get(&ctx.provider_id1).unwrap(); + // println!("{:?}", account1); + // let account_balance = ink_env::balance(&ctx.provider_id0); + // println!("{:?}", account_balance); +} fn bucket_settle_payment(ctx: &mut TestCluster, test_bucket: &TestBucket) { // Go to the future when some revenues are due. diff --git a/bucket/lib.rs b/bucket/lib.rs index eeaaad27..4da39514 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -31,7 +31,7 @@ pub mod ddc_bucket { use self::buckets_perms::store::BucketsPermsStore; use self::cdn_cluster::store::CdnClusterStore; - use self::cdn_node::entity::{CdnNodeStatus, NodeId}; + use self::cdn_node::entity::{CdnNodeStatus, CdnNodeKey, CdnNodeParams}; use self::protocol::store::ProtocolStore; use self::topology::store::TopologyStore; @@ -66,7 +66,6 @@ pub mod ddc_bucket { cdn_clusters: CdnClusterStore, cluster_params: ParamsStore, cdn_nodes: CdnNodeStore, - cdn_node_params: ParamsStore, nodes: NodeStore, accounts: AccountStore, perms: PermStore, @@ -96,8 +95,7 @@ pub mod ddc_bucket { // Reserve IDs 0. let _ = contract.accounts.create_if_not_exist(AccountId::default()); - let _ = contract.cdn_nodes.create(AccountId::default(), 0, AccountId::default()); - let _ = contract.cdn_node_params.create("".to_string()).unwrap(); + let _ = contract.cdn_nodes.create(AccountId::default(), AccountId::default(), "".to_string(), 0); let _ = contract .nodes .create( @@ -502,8 +500,8 @@ pub mod ddc_bucket { /// /// The CDN node ids are provided, which will form a cluster. #[ink(message, payable)] - pub fn cdn_cluster_create(&mut self, cdn_node_ids: Vec) -> ClusterId { - self.message_cdn_cluster_create(cdn_node_ids).unwrap() + pub fn cdn_cluster_create(&mut self, cdn_node_keys: Vec) -> ClusterId { + self.message_cdn_cluster_create(cdn_node_keys).unwrap() } /// Set rate for streaming (price per gb) @@ -526,7 +524,7 @@ pub mod ddc_bucket { &mut self, cluster_id: ClusterId, aggregates_accounts: Vec<(AccountId, u128)>, - aggregates_nodes: Vec<(u32, u128)>, + aggregates_nodes: Vec<(CdnNodeKey, u128)>, aggregates_buckets: Vec<(BucketId, Resource)>, era: u64, ) -> () { @@ -580,20 +578,20 @@ pub mod ddc_bucket { impl DdcBucket { /// CDN node operator sets the commit for current era. #[ink(message)] - pub fn set_commit(&mut self, cdn_owner: AccountId, node_id: NodeId, commit: Commit) { - self.message_set_commit(cdn_owner, node_id, commit); + pub fn set_commit(&mut self, cdn_owner: AccountId, cdn_node_key: CdnNodeKey, commit: Commit) { + self.message_set_commit(cdn_owner, cdn_node_key, commit); } /// Return the last commit submitted by CDN node operator #[ink(message)] - pub fn get_commit(&self, cdn_owner: AccountId) -> Vec<(NodeId, Commit)> { + pub fn get_commit(&self, cdn_owner: AccountId) -> Vec<(CdnNodeKey, Commit)> { self.message_get_commit(cdn_owner) } /// Return last era validated per CDN node #[ink(message)] - pub fn get_validated_commit(&self, node: NodeId) -> EraAndTimestamp { - self.message_get_validated_commit(node) + pub fn get_validated_commit(&self, cdn_node_key: CdnNodeKey) -> EraAndTimestamp { + self.message_get_validated_commit(cdn_node_key) } /// Set the new configs for era @@ -623,9 +621,10 @@ pub mod ddc_bucket { #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] pub struct CdnNodeCreated { #[ink(topic)] - node_id: NodeId, + cdn_node_key: CdnNodeKey, #[ink(topic)] provider_id: AccountId, + cdn_node_params: CdnNodeParams, undistributed_payment: Balance, } @@ -648,29 +647,23 @@ pub mod ddc_bucket { /// /// `node_params` is configuration used by clients and nodes. In particular, this contains the URL to the service. See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema) #[ink(message, payable)] - pub fn cdn_node_create(&mut self, node_params: Params, pubkey: AccountId) -> NodeId { - self.message_cdn_node_create(node_params, pubkey).unwrap() + pub fn cdn_node_create(&mut self, cdn_node_key: CdnNodeKey, cdn_node_params: CdnNodeParams) -> CdnNodeKey { + self.message_cdn_node_create(cdn_node_key, cdn_node_params).unwrap() } /// Change the `node_params`, which is configuration used by clients and nodes. /// /// See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema) #[ink(message, payable)] - pub fn cdn_node_change_params(&mut self, node_id: NodeId, params: NodeParams) { - self.message_cdn_node_change_params(node_id, params) + pub fn cdn_node_change_params(&mut self, cdn_node_key: CdnNodeKey, cdn_node_params: CdnNodeParams) { + self.message_cdn_node_change_params(cdn_node_key, cdn_node_params) .unwrap(); } /// Get the current state of the cdn node #[ink(message)] - pub fn cdn_node_get(&self, node_id: NodeId) -> Result { - self.message_cdn_node_get(node_id) - } - - /// Get the current state of a cdn node by a public key. - #[ink(message)] - pub fn cdn_node_get_by_pubkey(&self, pubkey: AccountId) -> Result { - self.message_cdn_node_get_by_pub_key(pubkey) + pub fn cdn_node_get(&self, cdn_node_key: CdnNodeKey) -> Result { + self.message_cdn_node_get(cdn_node_key) } /// Iterate through all nodes. @@ -695,8 +688,8 @@ pub mod ddc_bucket { /// /// The underlying algorithm swaps the moved to be removed with the last one added, hence the id of the last one added will be updated #[ink(message)] - pub fn cdn_node_remove(&mut self, node_id: NodeId) -> Result<()> { - self.message_remove_cdn_node(node_id) + pub fn cdn_node_remove(&mut self, node_key: CdnNodeKey) -> Result<()> { + self.message_remove_cdn_node(node_key) } } // ---- End CDN Node ---- @@ -750,8 +743,8 @@ pub mod ddc_bucket { /// /// See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema) #[ink(message, payable)] - pub fn node_change_params(&mut self, node_key: NodeKey, params: NodeParams) { - self.message_node_change_params(node_key, params).unwrap(); + pub fn node_change_params(&mut self, node_key: NodeKey, node_params: NodeParams) { + self.message_node_change_params(node_key, node_params).unwrap(); } /// Get the current status of a node. @@ -965,7 +958,9 @@ pub mod ddc_bucket { BucketClusterAlreadyConnected, BucketClusterNotSetup, NodeDoesNotExist, + CdnNodeDoesNotExist, NodeAlreadyExists, + CdnNodeAlreadyExists, FlowDoesNotExist, AccountDoesNotExist, ParamsDoesNotExist, diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index d246728f..45d3bbb1 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -1,6 +1,6 @@ { "source": { - "hash": "0x18503c5dfa90d2550281e403227f06fa25d25cb370f0bc19b9652aed48e0a2dc", + "hash": "0x19a976019a0941557f65c9b14590151e8683acea62f0fb378fdc3d71c154a28e", "language": "ink! 3.4.0", "compiler": "rustc 1.69.0-nightly" }, @@ -357,12 +357,12 @@ { "docs": [], "indexed": true, - "label": "node_id", + "label": "cdn_node_key", "type": { "displayName": [ - "NodeId" + "CdnNodeKey" ], - "type": 5 + "type": 2 } }, { @@ -376,6 +376,17 @@ "type": 2 } }, + { + "docs": [], + "indexed": false, + "label": "cdn_node_params", + "type": { + "displayName": [ + "CdnNodeParams" + ], + "type": 14 + } + }, { "docs": [], "indexed": false, @@ -496,7 +507,7 @@ "displayName": [ "Permission" ], - "type": 78 + "type": 74 } } ], @@ -526,7 +537,7 @@ "displayName": [ "Permission" ], - "type": 78 + "type": 74 } } ], @@ -563,7 +574,7 @@ "displayName": [ "Option" ], - "type": 43 + "type": 41 } } ], @@ -618,7 +629,7 @@ "payable": true, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0xc7d0c2cd" }, @@ -653,7 +664,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0x4c482d19" }, @@ -732,7 +743,7 @@ "displayName": [ "Result" ], - "type": 45 + "type": 43 }, "selector": "0x3802cb77" }, @@ -762,7 +773,7 @@ "displayName": [ "Option" ], - "type": 43 + "type": 41 } } ], @@ -779,7 +790,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 49 + "type": 47 }, "selector": "0x417ab584" }, @@ -840,7 +851,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0x053eb3ce" }, @@ -873,7 +884,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0x85010c6d" }, @@ -932,7 +943,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0xea2e477a" }, @@ -965,7 +976,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0x2b3d8dd1" }, @@ -1024,7 +1035,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0xfc0e94ea" }, @@ -1057,7 +1068,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0xe9bfed5a" }, @@ -1233,7 +1244,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0xb5e38125" }, @@ -1254,7 +1265,7 @@ "displayName": [ "NodeTag" ], - "type": 29 + "type": 27 } } ], @@ -1266,7 +1277,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0x9640d48e" }, @@ -1310,7 +1321,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0x48194ab1" }, @@ -1389,7 +1400,7 @@ "displayName": [ "Result" ], - "type": 51 + "type": 49 }, "selector": "0xe75411f5" }, @@ -1419,7 +1430,7 @@ "displayName": [ "Option" ], - "type": 43 + "type": 41 } } ], @@ -1436,19 +1447,19 @@ "payable": false, "returnType": { "displayName": [], - "type": 53 + "type": 51 }, "selector": "0xd9db9d44" }, { "args": [ { - "label": "cdn_node_ids", + "label": "cdn_node_keys", "type": { "displayName": [ "Vec" ], - "type": 23 + "type": 11 } } ], @@ -1499,7 +1510,7 @@ "payable": true, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0x7578922a" }, @@ -1546,7 +1557,7 @@ "displayName": [ "Vec" ], - "type": 55 + "type": 53 } }, { @@ -1555,7 +1566,7 @@ "displayName": [ "Vec" ], - "type": 57 + "type": 53 } }, { @@ -1564,7 +1575,7 @@ "displayName": [ "Vec" ], - "type": 59 + "type": 55 } }, { @@ -1587,7 +1598,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0x7219be3f" }, @@ -1638,7 +1649,7 @@ "displayName": [ "Result" ], - "type": 61 + "type": 57 }, "selector": "0x4b22fbf1" }, @@ -1668,7 +1679,7 @@ "displayName": [ "Option" ], - "type": 43 + "type": 41 } } ], @@ -1685,7 +1696,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 63 + "type": 59 }, "selector": "0xb242a64f" }, @@ -1701,12 +1712,12 @@ } }, { - "label": "node_id", + "label": "cdn_node_key", "type": { "displayName": [ - "NodeId" + "CdnNodeKey" ], - "type": 5 + "type": 2 } }, { @@ -1715,7 +1726,7 @@ "displayName": [ "Commit" ], - "type": 37 + "type": 35 } } ], @@ -1750,19 +1761,19 @@ "displayName": [ "Vec" ], - "type": 35 + "type": 33 }, "selector": "0x5329f551" }, { "args": [ { - "label": "node", + "label": "cdn_node_key", "type": { "displayName": [ - "NodeId" + "CdnNodeKey" ], - "type": 5 + "type": 2 } } ], @@ -1776,7 +1787,7 @@ "displayName": [ "EraAndTimestamp" ], - "type": 40 + "type": 38 }, "selector": "0x7d497bc1" }, @@ -1788,7 +1799,7 @@ "displayName": [ "EraConfig" ], - "type": 65 + "type": 61 } } ], @@ -1800,7 +1811,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0x49a5b8f7" }, @@ -1816,7 +1827,7 @@ "displayName": [ "EraStatus" ], - "type": 66 + "type": 62 }, "selector": "0x617f696b" }, @@ -1832,7 +1843,7 @@ "displayName": [ "EraConfig" ], - "type": 65 + "type": 61 }, "selector": "0x84b61468" }, @@ -1881,21 +1892,21 @@ { "args": [ { - "label": "node_params", + "label": "cdn_node_key", "type": { "displayName": [ - "Params" + "CdnNodeKey" ], - "type": 14 + "type": 2 } }, { - "label": "pubkey", + "label": "cdn_node_params", "type": { "displayName": [ - "AccountId" + "CdnNodeParams" ], - "type": 2 + "type": 14 } } ], @@ -1911,28 +1922,28 @@ "payable": true, "returnType": { "displayName": [ - "NodeId" + "CdnNodeKey" ], - "type": 5 + "type": 2 }, "selector": "0xe8aa4ade" }, { "args": [ { - "label": "node_id", + "label": "cdn_node_key", "type": { "displayName": [ - "NodeId" + "CdnNodeKey" ], - "type": 5 + "type": 2 } }, { - "label": "params", + "label": "cdn_node_params", "type": { "displayName": [ - "NodeParams" + "CdnNodeParams" ], "type": 14 } @@ -1952,12 +1963,12 @@ { "args": [ { - "label": "node_id", + "label": "cdn_node_key", "type": { "displayName": [ - "NodeId" + "CdnNodeKey" ], - "type": 5 + "type": 2 } } ], @@ -1971,36 +1982,10 @@ "displayName": [ "Result" ], - "type": 68 + "type": 64 }, "selector": "0xf9a5a813" }, - { - "args": [ - { - "label": "pubkey", - "type": { - "displayName": [ - "AccountId" - ], - "type": 2 - } - } - ], - "docs": [ - " Get the current state of a cdn node by a public key." - ], - "label": "cdn_node_get_by_pubkey", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 68 - }, - "selector": "0x17d7ffe8" - }, { "args": [ { @@ -2027,7 +2012,7 @@ "displayName": [ "Option" ], - "type": 43 + "type": 41 } } ], @@ -2044,19 +2029,19 @@ "payable": false, "returnType": { "displayName": [], - "type": 70 + "type": 66 }, "selector": "0xf8589aae" }, { "args": [ { - "label": "node_id", + "label": "node_key", "type": { "displayName": [ - "NodeId" + "CdnNodeKey" ], - "type": 5 + "type": 2 } } ], @@ -2074,7 +2059,7 @@ "displayName": [ "Result" ], - "type": 72 + "type": 68 }, "selector": "0xe068fb34" }, @@ -2164,7 +2149,7 @@ "displayName": [ "NodeTag" ], - "type": 29 + "type": 27 } } ], @@ -2198,7 +2183,7 @@ } }, { - "label": "params", + "label": "node_params", "type": { "displayName": [ "NodeParams" @@ -2240,7 +2225,7 @@ "displayName": [ "Result" ], - "type": 73 + "type": 69 }, "selector": "0x847f3997" }, @@ -2270,7 +2255,7 @@ "displayName": [ "Option" ], - "type": 43 + "type": 41 } } ], @@ -2287,7 +2272,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 75 + "type": 71 }, "selector": "0x423286d6" }, @@ -2317,7 +2302,7 @@ "displayName": [ "Result" ], - "type": 72 + "type": 68 }, "selector": "0x42e5f273" }, @@ -2357,7 +2342,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0xc5e3e2ca" }, @@ -2397,7 +2382,7 @@ "payable": false, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0x85c6fa6d" }, @@ -2412,7 +2397,7 @@ "payable": true, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0xc311af62" }, @@ -2436,7 +2421,7 @@ "payable": true, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0xe9fad0bf" }, @@ -2460,7 +2445,7 @@ "payable": true, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0xf7ea2c67" }, @@ -2476,7 +2461,7 @@ "payable": true, "returnType": { "displayName": [], - "type": 44 + "type": 42 }, "selector": "0x98173716" }, @@ -2502,7 +2487,7 @@ "displayName": [ "Result" ], - "type": 77 + "type": 73 }, "selector": "0x1d4220fa" }, @@ -2562,7 +2547,7 @@ "displayName": [ "Permission" ], - "type": 78 + "type": 74 } } ], @@ -2598,7 +2583,7 @@ "displayName": [ "Permission" ], - "type": 78 + "type": 74 } } ], @@ -2628,7 +2613,7 @@ "displayName": [ "Permission" ], - "type": 78 + "type": 74 } } ], @@ -2672,7 +2657,7 @@ "displayName": [ "FeeConfig" ], - "type": 79 + "type": 75 } } ], @@ -2831,19 +2816,19 @@ "layout": { "cell": { "key": "0x0700000000000000000000000000000000000000000000000000000000000000", - "ty": 24 + "ty": 23 } }, - "name": "pub_key_to_node" + "name": "cdn_nodes" }, { "layout": { "cell": { "key": "0x0800000000000000000000000000000000000000000000000000000000000000", - "ty": 25 + "ty": 11 } }, - "name": "cdn_nodes" + "name": "keys" } ] } @@ -2858,25 +2843,7 @@ "layout": { "cell": { "key": "0x0900000000000000000000000000000000000000000000000000000000000000", - "ty": 13 - } - }, - "name": null - } - ] - } - }, - "name": "cdn_node_params" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0a00000000000000000000000000000000000000000000000000000000000000", - "ty": 27 + "ty": 25 } }, "name": "nodes" @@ -2884,7 +2851,7 @@ { "layout": { "cell": { - "key": "0x0b00000000000000000000000000000000000000000000000000000000000000", + "key": "0x0a00000000000000000000000000000000000000000000000000000000000000", "ty": 11 } }, @@ -2902,8 +2869,8 @@ { "layout": { "cell": { - "key": "0x0c00000000000000000000000000000000000000000000000000000000000000", - "ty": 30 + "key": "0x0b00000000000000000000000000000000000000000000000000000000000000", + "ty": 28 } }, "name": null @@ -2915,7 +2882,7 @@ { "layout": { "cell": { - "key": "0x0d00000000000000000000000000000000000000000000000000000000000000", + "key": "0x0c00000000000000000000000000000000000000000000000000000000000000", "ty": 8 } }, @@ -2929,7 +2896,7 @@ { "layout": { "cell": { - "key": "0x0e00000000000000000000000000000000000000000000000000000000000000", + "key": "0x0d00000000000000000000000000000000000000000000000000000000000000", "ty": 11 } }, @@ -2947,8 +2914,8 @@ { "layout": { "cell": { - "key": "0x0f00000000000000000000000000000000000000000000000000000000000000", - "ty": 32 + "key": "0x0e00000000000000000000000000000000000000000000000000000000000000", + "ty": 30 } }, "name": null @@ -2969,7 +2936,7 @@ { "layout": { "cell": { - "key": "0x1000000000000000000000000000000000000000000000000000000000000000", + "key": "0x0f00000000000000000000000000000000000000000000000000000000000000", "ty": 8 } }, @@ -2978,7 +2945,7 @@ { "layout": { "cell": { - "key": "0x1100000000000000000000000000000000000000000000000000000000000000", + "key": "0x1000000000000000000000000000000000000000000000000000000000000000", "ty": 2 } }, @@ -2987,7 +2954,7 @@ { "layout": { "cell": { - "key": "0x1200000000000000000000000000000000000000000000000000000000000000", + "key": "0x1100000000000000000000000000000000000000000000000000000000000000", "ty": 8 } }, @@ -3010,7 +2977,7 @@ { "layout": { "cell": { - "key": "0x1300000000000000000000000000000000000000000000000000000000000000", + "key": "0x1200000000000000000000000000000000000000000000000000000000000000", "ty": 2 } }, @@ -3019,8 +2986,8 @@ { "layout": { "cell": { - "key": "0x1400000000000000000000000000000000000000000000000000000000000000", - "ty": 34 + "key": "0x1300000000000000000000000000000000000000000000000000000000000000", + "ty": 32 } }, "name": "commits" @@ -3028,8 +2995,8 @@ { "layout": { "cell": { - "key": "0x1500000000000000000000000000000000000000000000000000000000000000", - "ty": 39 + "key": "0x1400000000000000000000000000000000000000000000000000000000000000", + "ty": 37 } }, "name": "validated_commits" @@ -3041,7 +3008,7 @@ { "layout": { "cell": { - "key": "0x1600000000000000000000000000000000000000000000000000000000000000", + "key": "0x1500000000000000000000000000000000000000000000000000000000000000", "ty": 20 } }, @@ -3050,7 +3017,7 @@ { "layout": { "cell": { - "key": "0x1700000000000000000000000000000000000000000000000000000000000000", + "key": "0x1600000000000000000000000000000000000000000000000000000000000000", "ty": 20 } }, @@ -3059,7 +3026,7 @@ { "layout": { "cell": { - "key": "0x1800000000000000000000000000000000000000000000000000000000000000", + "key": "0x1700000000000000000000000000000000000000000000000000000000000000", "ty": 20 } }, @@ -3068,7 +3035,7 @@ { "layout": { "cell": { - "key": "0x1900000000000000000000000000000000000000000000000000000000000000", + "key": "0x1800000000000000000000000000000000000000000000000000000000000000", "ty": 20 } }, @@ -3091,7 +3058,7 @@ { "layout": { "cell": { - "key": "0x1a00000000000000000000000000000000000000000000000000000000000000", + "key": "0x1900000000000000000000000000000000000000000000000000000000000000", "ty": 2 } }, @@ -3100,7 +3067,7 @@ { "layout": { "cell": { - "key": "0x1b00000000000000000000000000000000000000000000000000000000000000", + "key": "0x1a00000000000000000000000000000000000000000000000000000000000000", "ty": 5 } }, @@ -3113,7 +3080,7 @@ { "layout": { "cell": { - "key": "0x1c00000000000000000000000000000000000000000000000000000000000000", + "key": "0x1b00000000000000000000000000000000000000000000000000000000000000", "ty": 8 } }, @@ -3136,8 +3103,8 @@ { "layout": { "cell": { - "key": "0x1d00000000000000000000000000000000000000000000000000000000000000", - "ty": 41 + "key": "0x1c00000000000000000000000000000000000000000000000000000000000000", + "ty": 39 } }, "name": null @@ -3541,8 +3508,8 @@ }, { "name": "cdn_nodes", - "type": 23, - "typeName": "Vec" + "type": 11, + "typeName": "Vec" }, { "name": "resources_used", @@ -3573,16 +3540,6 @@ }, { "id": 23, - "type": { - "def": { - "sequence": { - "type": 5 - } - } - } - }, - { - "id": 24, "type": { "def": { "composite": { @@ -3602,7 +3559,7 @@ }, { "name": "V", - "type": 5 + "type": 24 } ], "path": [ @@ -3614,17 +3571,7 @@ } }, { - "id": 25, - "type": { - "def": { - "sequence": { - "type": 26 - } - } - } - }, - { - "id": 26, + "id": 24, "type": { "def": { "composite": { @@ -3640,9 +3587,9 @@ "typeName": "Balance" }, { - "name": "node_pub_key", - "type": 2, - "typeName": "CdnNodePublicKey" + "name": "cdn_node_params", + "type": 14, + "typeName": "CdnNodeParams" } ] } @@ -3657,7 +3604,7 @@ } }, { - "id": 27, + "id": 25, "type": { "def": { "composite": { @@ -3677,7 +3624,7 @@ }, { "name": "V", - "type": 28 + "type": 26 } ], "path": [ @@ -3689,7 +3636,7 @@ } }, { - "id": 28, + "id": 26, "type": { "def": { "composite": { @@ -3711,7 +3658,7 @@ }, { "name": "node_tag", - "type": 29, + "type": 27, "typeName": "NodeTag" }, { @@ -3732,7 +3679,7 @@ } }, { - "id": 29, + "id": 27, "type": { "def": { "variant": { @@ -3770,7 +3717,7 @@ } }, { - "id": 30, + "id": 28, "type": { "def": { "composite": { @@ -3790,7 +3737,7 @@ }, { "name": "V", - "type": 31 + "type": 29 } ], "path": [ @@ -3802,7 +3749,7 @@ } }, { - "id": 31, + "id": 29, "type": { "def": { "composite": { @@ -3850,7 +3797,7 @@ } }, { - "id": 32, + "id": 30, "type": { "def": { "composite": { @@ -3866,7 +3813,7 @@ "params": [ { "name": "K", - "type": 33 + "type": 31 }, { "name": "V", @@ -3882,7 +3829,7 @@ } }, { - "id": 33, + "id": 31, "type": { "def": { "sequence": { @@ -3892,7 +3839,7 @@ } }, { - "id": 34, + "id": 32, "type": { "def": { "composite": { @@ -3912,7 +3859,7 @@ }, { "name": "V", - "type": 35 + "type": 33 } ], "path": [ @@ -3924,35 +3871,35 @@ } }, { - "id": 35, + "id": 33, "type": { "def": { "sequence": { - "type": 36 + "type": 34 } } } }, { - "id": 36, + "id": 34, "type": { "def": { "tuple": [ - 5, - 37 + 2, + 35 ] } } }, { - "id": 37, + "id": 35, "type": { "def": { "composite": { "fields": [ { "name": "hash", - "type": 38, + "type": 36, "typeName": "Hash" }, { @@ -3983,7 +3930,7 @@ } }, { - "id": 38, + "id": 36, "type": { "def": { "composite": { @@ -4003,7 +3950,7 @@ } }, { - "id": 39, + "id": 37, "type": { "def": { "composite": { @@ -4019,11 +3966,11 @@ "params": [ { "name": "K", - "type": 5 + "type": 2 }, { "name": "V", - "type": 40 + "type": 38 } ], "path": [ @@ -4035,7 +3982,7 @@ } }, { - "id": 40, + "id": 38, "type": { "def": { "tuple": [ @@ -4046,7 +3993,7 @@ } }, { - "id": 41, + "id": 39, "type": { "def": { "composite": { @@ -4062,7 +4009,7 @@ "params": [ { "name": "K", - "type": 42 + "type": 40 }, { "name": "V", @@ -4078,7 +4025,7 @@ } }, { - "id": 42, + "id": 40, "type": { "def": { "tuple": [ @@ -4089,7 +4036,7 @@ } }, { - "id": 43, + "id": 41, "type": { "def": { "variant": { @@ -4122,7 +4069,7 @@ } }, { - "id": 44, + "id": 42, "type": { "def": { "tuple": [] @@ -4130,7 +4077,7 @@ } }, { - "id": 45, + "id": 43, "type": { "def": { "variant": { @@ -4138,7 +4085,7 @@ { "fields": [ { - "type": 46 + "type": 44 } ], "index": 0, @@ -4147,7 +4094,7 @@ { "fields": [ { - "type": 48 + "type": 46 } ], "index": 1, @@ -4159,11 +4106,11 @@ "params": [ { "name": "T", - "type": 46 + "type": 44 }, { "name": "E", - "type": 48 + "type": 46 } ], "path": [ @@ -4172,7 +4119,7 @@ } }, { - "id": 46, + "id": 44, "type": { "def": { "composite": { @@ -4184,7 +4131,7 @@ }, { "name": "bucket", - "type": 47, + "type": 45, "typeName": "BucketInStatus" }, { @@ -4220,7 +4167,7 @@ } }, { - "id": 47, + "id": 45, "type": { "def": { "composite": { @@ -4263,7 +4210,7 @@ } }, { - "id": 48, + "id": 46, "type": { "def": { "variant": { @@ -4302,54 +4249,62 @@ }, { "index": 8, - "name": "NodeAlreadyExists" + "name": "CdnNodeDoesNotExist" }, { "index": 9, - "name": "FlowDoesNotExist" + "name": "NodeAlreadyExists" }, { "index": 10, - "name": "AccountDoesNotExist" + "name": "CdnNodeAlreadyExists" }, { "index": 11, - "name": "ParamsDoesNotExist" + "name": "FlowDoesNotExist" }, { "index": 12, - "name": "UnauthorizedProvider" + "name": "AccountDoesNotExist" }, { "index": 13, - "name": "UnauthorizedOwner" + "name": "ParamsDoesNotExist" }, { "index": 14, - "name": "UnauthorizedClusterManager" + "name": "UnauthorizedProvider" }, { "index": 15, - "name": "ClusterManagerIsNotTrusted" + "name": "UnauthorizedOwner" }, { "index": 16, - "name": "TransferFailed" + "name": "UnauthorizedClusterManager" }, { "index": 17, - "name": "InsufficientBalance" + "name": "ClusterManagerIsNotTrusted" }, { "index": 18, - "name": "InsufficientResources" + "name": "TransferFailed" }, { "index": 19, - "name": "Unauthorized" + "name": "InsufficientBalance" }, { "index": 20, + "name": "InsufficientResources" + }, + { + "index": 21, + "name": "Unauthorized" + }, + { + "index": 22, "name": "UnknownNode" } ] @@ -4363,28 +4318,28 @@ } }, { - "id": 49, + "id": 47, "type": { "def": { "tuple": [ - 50, + 48, 5 ] } } }, { - "id": 50, + "id": 48, "type": { "def": { "sequence": { - "type": 46 + "type": 44 } } } }, { - "id": 51, + "id": 49, "type": { "def": { "variant": { @@ -4392,7 +4347,7 @@ { "fields": [ { - "type": 52 + "type": 50 } ], "index": 0, @@ -4401,7 +4356,7 @@ { "fields": [ { - "type": 48 + "type": 46 } ], "index": 1, @@ -4413,11 +4368,11 @@ "params": [ { "name": "T", - "type": 52 + "type": 50 }, { "name": "E", - "type": 48 + "type": 46 } ], "path": [ @@ -4426,7 +4381,7 @@ } }, { - "id": 52, + "id": 50, "type": { "def": { "composite": { @@ -4459,38 +4414,38 @@ } }, { - "id": 53, + "id": 51, "type": { "def": { "tuple": [ - 54, + 52, 5 ] } } }, { - "id": 54, + "id": 52, "type": { "def": { "sequence": { - "type": 52 + "type": 50 } } } }, { - "id": 55, + "id": 53, "type": { "def": { "sequence": { - "type": 56 + "type": 54 } } } }, { - "id": 56, + "id": 54, "type": { "def": { "tuple": [ @@ -4501,38 +4456,17 @@ } }, { - "id": 57, - "type": { - "def": { - "sequence": { - "type": 58 - } - } - } - }, - { - "id": 58, - "type": { - "def": { - "tuple": [ - 5, - 8 - ] - } - } - }, - { - "id": 59, + "id": 55, "type": { "def": { "sequence": { - "type": 60 + "type": 56 } } } }, { - "id": 60, + "id": 56, "type": { "def": { "tuple": [ @@ -4543,7 +4477,7 @@ } }, { - "id": 61, + "id": 57, "type": { "def": { "variant": { @@ -4551,7 +4485,7 @@ { "fields": [ { - "type": 62 + "type": 58 } ], "index": 0, @@ -4560,7 +4494,7 @@ { "fields": [ { - "type": 48 + "type": 46 } ], "index": 1, @@ -4572,11 +4506,11 @@ "params": [ { "name": "T", - "type": 62 + "type": 58 }, { "name": "E", - "type": 48 + "type": 46 } ], "path": [ @@ -4585,7 +4519,7 @@ } }, { - "id": 62, + "id": 58, "type": { "def": { "composite": { @@ -4613,28 +4547,28 @@ } }, { - "id": 63, + "id": 59, "type": { "def": { "tuple": [ - 64, + 60, 5 ] } } }, { - "id": 64, + "id": 60, "type": { "def": { "sequence": { - "type": 62 + "type": 58 } } } }, { - "id": 65, + "id": 61, "type": { "def": { "composite": { @@ -4672,7 +4606,7 @@ } }, { - "id": 66, + "id": 62, "type": { "def": { "composite": { @@ -4684,7 +4618,7 @@ }, { "name": "current_phase", - "type": 67, + "type": 63, "typeName": "Phase" }, { @@ -4715,7 +4649,7 @@ } }, { - "id": 67, + "id": 63, "type": { "def": { "variant": { @@ -4745,7 +4679,7 @@ } }, { - "id": 68, + "id": 64, "type": { "def": { "variant": { @@ -4753,7 +4687,7 @@ { "fields": [ { - "type": 69 + "type": 65 } ], "index": 0, @@ -4762,7 +4696,7 @@ { "fields": [ { - "type": 48 + "type": 46 } ], "index": 1, @@ -4774,11 +4708,11 @@ "params": [ { "name": "T", - "type": 69 + "type": 65 }, { "name": "E", - "type": 48 + "type": 46 } ], "path": [ @@ -4787,25 +4721,20 @@ } }, { - "id": 69, + "id": 65, "type": { "def": { "composite": { "fields": [ { - "name": "node_id", - "type": 5, - "typeName": "NodeId" + "name": "cdn_node_key", + "type": 2, + "typeName": "CdnNodeKey" }, { - "name": "node", - "type": 26, + "name": "cdn_node", + "type": 24, "typeName": "CdnNode" - }, - { - "name": "params", - "type": 14, - "typeName": "Params" } ] } @@ -4820,28 +4749,28 @@ } }, { - "id": 70, + "id": 66, "type": { "def": { "tuple": [ - 71, + 67, 5 ] } } }, { - "id": 71, + "id": 67, "type": { "def": { "sequence": { - "type": 69 + "type": 65 } } } }, { - "id": 72, + "id": 68, "type": { "def": { "variant": { @@ -4849,7 +4778,7 @@ { "fields": [ { - "type": 44 + "type": 42 } ], "index": 0, @@ -4858,7 +4787,7 @@ { "fields": [ { - "type": 48 + "type": 46 } ], "index": 1, @@ -4870,11 +4799,11 @@ "params": [ { "name": "T", - "type": 44 + "type": 42 }, { "name": "E", - "type": 48 + "type": 46 } ], "path": [ @@ -4883,7 +4812,7 @@ } }, { - "id": 73, + "id": 69, "type": { "def": { "variant": { @@ -4891,7 +4820,7 @@ { "fields": [ { - "type": 74 + "type": 70 } ], "index": 0, @@ -4900,7 +4829,7 @@ { "fields": [ { - "type": 48 + "type": 46 } ], "index": 1, @@ -4912,11 +4841,11 @@ "params": [ { "name": "T", - "type": 74 + "type": 70 }, { "name": "E", - "type": 48 + "type": 46 } ], "path": [ @@ -4925,7 +4854,7 @@ } }, { - "id": 74, + "id": 70, "type": { "def": { "composite": { @@ -4937,7 +4866,7 @@ }, { "name": "node", - "type": 28, + "type": 26, "typeName": "Node" } ] @@ -4953,28 +4882,28 @@ } }, { - "id": 75, + "id": 71, "type": { "def": { "tuple": [ - 76, + 72, 5 ] } } }, { - "id": 76, + "id": 72, "type": { "def": { "sequence": { - "type": 74 + "type": 70 } } } }, { - "id": 77, + "id": 73, "type": { "def": { "variant": { @@ -4982,7 +4911,7 @@ { "fields": [ { - "type": 31 + "type": 29 } ], "index": 0, @@ -4991,7 +4920,7 @@ { "fields": [ { - "type": 48 + "type": 46 } ], "index": 1, @@ -5003,11 +4932,11 @@ "params": [ { "name": "T", - "type": 31 + "type": 29 }, { "name": "E", - "type": 48 + "type": 46 } ], "path": [ @@ -5016,7 +4945,7 @@ } }, { - "id": 78, + "id": 74, "type": { "def": { "variant": { @@ -5052,7 +4981,7 @@ } }, { - "id": 79, + "id": 75, "type": { "def": { "composite": { From 961d7bd749e872d5577a379a4c9c49c29530e4c7 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Tue, 13 Jun 2023 13:57:13 +0200 Subject: [PATCH 03/89] chore(node): replacing integer id with pub key --- bucket/ddc_bucket/cluster/messages.rs | 10 ++--- bucket/ddc_bucket/tests/test_contract.rs | 4 +- bucket/lib.rs | 54 ++++++++++++++++-------- build-and-deploy.sh | 10 ++--- scripts/sdk/src/abi/ddc_bucket.json | 26 ++++++------ 5 files changed, 62 insertions(+), 42 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index b86b81bd..762a52dc 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -5,6 +5,7 @@ use ink_prelude::vec::Vec; use crate::ddc_bucket::cash::{Cash, Payable}; use crate::ddc_bucket::cluster::entity::{Cluster, ClusterStatus}; use crate::ddc_bucket::node::entity::{Node, NodeKey, Resource}; +use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; use crate::ddc_bucket::perm::entity::Permission; use crate::ddc_bucket::perm::store::PermStore; use crate::ddc_bucket::ClusterNodeReplaced; @@ -19,22 +20,22 @@ use super::entity::{ClusterId, ClusterParams}; impl DdcBucket { pub fn message_cluster_create( &mut self, + nodes_keys: Vec, v_nodes: Vec>, - node_keys: Vec, + cdn_nodes_keys: Vec, cluster_params: ClusterParams, ) -> Result { let manager = Self::env().caller(); let mut nodes = Vec::<(NodeKey, Node)>::new(); - for node_key in &node_keys { + for node_key in &nodes_keys { let node = self.nodes.get(*node_key)?; // Verify that the node provider trusts the cluster manager. Self::only_trusted_manager(&self.perms, manager, node.provider_id.clone())?; - nodes.push((*node_key, node)); } - let cluster_id = self.clusters.create(manager, &v_nodes, &node_keys)?; + let cluster_id = self.clusters.create(manager, &v_nodes, &nodes_keys)?; let rent = self .topology_store .create_topology(cluster_id, v_nodes, nodes.into_iter().map(|(key, node)| (key, node)).collect())?; @@ -65,7 +66,6 @@ impl DdcBucket { let node = self.nodes.get(*node_key)?; // Verify that the node provider trusts the cluster manager. Self::only_trusted_manager(&self.perms, manager, node.provider_id.clone())?; - nodes.push((*node_key, node)); } diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index 1348699b..51c10acc 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -571,9 +571,7 @@ fn cluster_management_validation_works() { assert_eq!( ctx.contract - .message_cluster_create(vec![ - vec![1, 2, 3], - ], vec![bad_node_id], "".to_string()), + .message_cluster_create(vec![vec![1, 2, 3]], vec![bad_node_id], vec![1, 2, 3], "".to_string()), Err(NodeDoesNotExist), "cluster initial nodes must exist" ); diff --git a/bucket/lib.rs b/bucket/lib.rs index 4da39514..16a192e3 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -355,50 +355,70 @@ pub mod ddc_bucket { } impl DdcBucket { - /// Removes a node to an existing cluster + /// Adds a Storage node to the targeting cluster. /// - /// The caller will be its first manager. + /// This endpoint adds a physical Storage node along with its virtual nodes to the targeting cluster. + /// The node will be added to the end of the cluster nodes list. + /// Virtual nodes determines a token (position) on the ring in terms of Consistent Hashing. + /// + /// # Arguments + /// + /// * `cluster_id` - ID of the targeting cluster + /// * `node_key` - Public Key associated with the Storage node + /// * `v_nodes` - List of tokens (positions) related to the Storage node + /// + /// # Errors + /// + /// This endpoint will return `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. #[ink(message, payable)] - pub fn cluster_remove_node( + pub fn cluster_add_node( &mut self, cluster_id: ClusterId, - node_keys: Vec, - v_nodes: Vec>, + node_key: NodeKey, + v_nodes: Vec, ) { - self.message_cluster_add_node(cluster_id, node_keys, v_nodes) + self.message_cluster_add_node(cluster_id, node_key, v_nodes) .unwrap() } - /// Adds node to an existing cluster + /// Removes a Storage node from the targeting cluster. /// - /// The caller will be its first manager. + /// This endpoint removes a physical Storage node along with its virtual nodes from the targeting cluster. + /// + /// # Arguments + /// + /// * `cluster_id` - ID of the targeting cluster + /// * `node_key` - Public Key associated with the Storage node + /// + /// # Errors + /// + /// This endpoint will return `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. #[ink(message, payable)] - pub fn cluster_add_node( + pub fn cluster_remove_node( &mut self, cluster_id: ClusterId, - node_keys: Vec, - v_nodes: Vec>, + node_key: NodeKey, ) { - self.message_cluster_add_node(cluster_id, node_keys, v_nodes) + self.message_cluster_remove_node(cluster_id, node_key) .unwrap() } - /// Create a new cluster and return its `cluster_id`. + /// Creates a new cluster and returns its `cluster_id`. /// /// The caller will be its first manager. /// - /// The cluster is split in a number of vnodes. The vnodes are assigned to the given physical nodes in a round-robin. Only nodes of providers that trust the cluster manager can be used (see `node_trust_manager`). The assignment can be changed with the function `cluster_replace_node`. + /// The cluster can contain both Storage and CDN nodes. The `v_nodes` are assigned to the given Storage physical nodes in a round-robin. Only nodes of providers that trust the cluster manager can be used (see `node_trust_manager`). The assignment can be changed with the function `cluster_replace_node`. /// /// `cluster_params` is configuration used by clients and nodes. In particular, this describes the semantics of vnodes. See the [data structure of ClusterParams](https://docs.cere.network/ddc/protocols/contract-params-schema) #[ink(message, payable)] pub fn cluster_create( &mut self, - _unused: AccountId, + nodes_keys: Vec, v_nodes: Vec>, - node_keys: Vec, + cdn_nodes_keys: Vec, cluster_params: ClusterParams, ) -> ClusterId { - self.message_cluster_create(v_nodes, node_keys, cluster_params) + self.message_cluster_create(nodes_keys, v_nodes, cdn_nodes_keys, cluster_params) .unwrap() } diff --git a/build-and-deploy.sh b/build-and-deploy.sh index 343ba632..c4021826 100755 --- a/build-and-deploy.sh +++ b/build-and-deploy.sh @@ -2,13 +2,13 @@ set -eu -cargo +nightly-2023-02-07 test +# cargo +nightly-2023-02-07 test cargo +nightly-2023-02-07 contract build --release --manifest-path bucket/Cargo.toml -cargo +nightly-2023-02-07 contract build --release --manifest-path ddc_nft_registry/Cargo.toml +# cargo +nightly-2023-02-07 contract build --release --manifest-path ddc_nft_registry/Cargo.toml cp target/ink/ddc_bucket/metadata.json scripts/sdk/src/abi/ddc_bucket.json -cp target/ink/ddc_nft_registry/metadata.json scripts/sdk/src/abi/ddc_nft_registry.json +# cp target/ink/ddc_nft_registry/metadata.json scripts/sdk/src/abi/ddc_nft_registry.json -yarn --cwd scripts deploy-ddc-bucket -yarn --cwd scripts deploy-ddc-nft-registry \ No newline at end of file +# yarn --cwd scripts deploy-ddc-bucket +# yarn --cwd scripts deploy-ddc-nft-registry \ No newline at end of file diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index 45d3bbb1..6ddb3046 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -1,6 +1,6 @@ { "source": { - "hash": "0x19a976019a0941557f65c9b14590151e8683acea62f0fb378fdc3d71c154a28e", + "hash": "0x74f1167a7247be04958655c6d3cfdee21a73146f183cabd7964ddddb5aaec722", "language": "ink! 3.4.0", "compiler": "rustc 1.69.0-nightly" }, @@ -1084,7 +1084,7 @@ } }, { - "label": "node_keys", + "label": "nodes_keys", "type": { "displayName": [ "Vec" @@ -1103,9 +1103,11 @@ } ], "docs": [ - " Removes a node to an existing cluster", + " Removes a set of Storage nodes from an existing cluster", + "", + " The index of virtual nodes in the `v_nodes` param must be aligned with the corresponding physical Storage node in the `nodes_keys` param", "", - " The caller will be its first manager." + " The caller must be its manager" ], "label": "cluster_remove_node", "mutates": true, @@ -1144,9 +1146,9 @@ } ], "docs": [ - " Adds node to an existing cluster", + " Adds a set of Storage nodes to an existing cluster", "", - " The caller will be its first manager." + " The caller must be its manager" ], "label": "cluster_add_node", "mutates": true, @@ -1157,12 +1159,12 @@ { "args": [ { - "label": "_unused", + "label": "nodes_keys", "type": { "displayName": [ - "AccountId" + "Vec" ], - "type": 2 + "type": 11 } }, { @@ -1175,7 +1177,7 @@ } }, { - "label": "node_keys", + "label": "cdn_nodes_keys", "type": { "displayName": [ "Vec" @@ -1194,11 +1196,11 @@ } ], "docs": [ - " Create a new cluster and return its `cluster_id`.", + " Creates a new cluster and returns its `cluster_id`.", "", " The caller will be its first manager.", "", - " The cluster is split in a number of vnodes. The vnodes are assigned to the given physical nodes in a round-robin. Only nodes of providers that trust the cluster manager can be used (see `node_trust_manager`). The assignment can be changed with the function `cluster_replace_node`.", + " The cluster can contain both Storage and CDN nodes. The `v_nodes` are assigned to the given Storage physical nodes in a round-robin. Only nodes of providers that trust the cluster manager can be used (see `node_trust_manager`). The assignment can be changed with the function `cluster_replace_node`.", "", " `cluster_params` is configuration used by clients and nodes. In particular, this describes the semantics of vnodes. See the [data structure of ClusterParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" ], From 10a9f9ee773b5a6fc51fc0cefa06290034e62cc1 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 15 Jun 2023 03:05:13 +0200 Subject: [PATCH 04/89] chore(node): dto object for node --- bucket/ddc_bucket/cdn_node/entity.rs | 2 +- bucket/ddc_bucket/cdn_node/messages.rs | 10 +- bucket/ddc_bucket/cluster/entity.rs | 2 +- bucket/ddc_bucket/cluster/messages.rs | 10 +- bucket/ddc_bucket/node/entity.rs | 16 +- bucket/ddc_bucket/node/messages.rs | 14 +- bucket/ddc_bucket/node/store.rs | 4 +- bucket/ddc_bucket/tests/test_contract.rs | 44 +- bucket/lib.rs | 1461 +++++++++++++++------- scripts/sdk/src/abi/ddc_bucket.json | 14 +- 10 files changed, 1049 insertions(+), 528 deletions(-) diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index 515ceb52..f2cd6d56 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -29,7 +29,7 @@ impl ink_storage::traits::PackedAllocate for CdnNode { #[derive(Clone, PartialEq, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] -pub struct CdnNodeStatus { +pub struct CdnNodeInfo { pub cdn_node_key: CdnNodeKey, pub cdn_node: CdnNode, } diff --git a/bucket/ddc_bucket/cdn_node/messages.rs b/bucket/ddc_bucket/cdn_node/messages.rs index 735853b6..b151eefc 100644 --- a/bucket/ddc_bucket/cdn_node/messages.rs +++ b/bucket/ddc_bucket/cdn_node/messages.rs @@ -5,7 +5,7 @@ use ink_prelude::vec::Vec; use crate::ddc_bucket::{AccountId, DdcBucket, CdnNodeCreated, Result, Balance}; use crate::ddc_bucket::perm::entity::{Permission}; -use super::entity::{CdnNodeKey, CdnNodeStatus, CdnNodeParams}; +use super::entity::{CdnNodeKey, CdnNodeInfo, CdnNodeParams}; impl DdcBucket { pub fn message_cdn_node_trust_manager(&mut self, manager: AccountId, is_trusted: bool) -> Result<()> { @@ -45,15 +45,15 @@ impl DdcBucket { Ok(()) } - pub fn message_cdn_node_get(&self, cdn_node_key: CdnNodeKey) -> Result { + pub fn message_cdn_node_get(&self, cdn_node_key: CdnNodeKey) -> Result { let cdn_node = self.cdn_nodes.get(cdn_node_key)?; - Ok(CdnNodeStatus { + Ok(CdnNodeInfo { cdn_node_key, cdn_node, }) } - pub fn message_cdn_node_list(&self, offset: u32, limit: u32, filter_provider_id: Option) -> (Vec, u32) { + pub fn message_cdn_node_list(&self, offset: u32, limit: u32, filter_provider_id: Option) -> (Vec, u32) { let mut cdn_nodes = Vec::with_capacity(limit as usize); for idx in offset..offset + limit { let cdn_node_key = match self.cdn_nodes.keys.get(idx as usize) { @@ -71,7 +71,7 @@ impl DdcBucket { } // Include the complete status of matched items. - let status = CdnNodeStatus { + let status = CdnNodeInfo { cdn_node_key, cdn_node, }; diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 6668f87e..112dd2ba 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -38,7 +38,7 @@ impl ink_storage::traits::PackedAllocate for Cluster { #[derive(Clone, PartialEq, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] -pub struct ClusterStatus { +pub struct ClusterInfo { pub cluster_id: ClusterId, pub cluster: Cluster, pub params: Params, diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 762a52dc..6292c5f8 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -3,7 +3,7 @@ use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; use crate::ddc_bucket::cash::{Cash, Payable}; -use crate::ddc_bucket::cluster::entity::{Cluster, ClusterStatus}; +use crate::ddc_bucket::cluster::entity::{Cluster, ClusterInfo}; use crate::ddc_bucket::node::entity::{Node, NodeKey, Resource}; use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; use crate::ddc_bucket::perm::entity::Permission; @@ -205,10 +205,10 @@ impl DdcBucket { Self::impl_change_params(&mut self.cluster_params, cluster_id, params) } - pub fn message_cluster_get(&self, cluster_id: ClusterId) -> Result { + pub fn message_cluster_get(&self, cluster_id: ClusterId) -> Result { let cluster = self.clusters.get(cluster_id)?.clone(); let params = self.cluster_params.get(cluster_id)?.clone(); - Ok(ClusterStatus { + Ok(ClusterInfo { cluster_id, cluster, params, @@ -220,7 +220,7 @@ impl DdcBucket { offset: u32, limit: u32, filter_manager_id: Option, - ) -> (Vec, u32) { + ) -> (Vec, u32) { let mut clusters = Vec::with_capacity(limit as usize); for cluster_id in offset..offset + limit { let cluster = match self.clusters.0.get(cluster_id as usize) { @@ -234,7 +234,7 @@ impl DdcBucket { } } // Include the complete status of matched items. - let status = ClusterStatus { + let status = ClusterInfo { cluster_id, cluster: cluster.clone(), params: self.cluster_params.get(cluster_id).unwrap().clone(), diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index 37274336..3690be0a 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -19,7 +19,7 @@ pub struct Node { pub provider_id: ProviderId, pub rent_per_month: Balance, pub free_resource: Resource, - pub node_tag: NodeTag, + pub node_tag: NodeStatus, pub node_params: NodeParams } @@ -33,7 +33,7 @@ impl ink_storage::traits::PackedAllocate for Node { #[derive(Clone, PartialEq, Encode, Decode, SpreadLayout, PackedLayout)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] -pub enum NodeTag { +pub enum NodeStatus { UNKNOWN, ACTIVE, ADDING, @@ -41,21 +41,21 @@ pub enum NodeTag { OFFLINE, } -impl SpreadAllocate for NodeTag { +impl SpreadAllocate for NodeStatus { fn allocate_spread(_: &mut KeyPtr) -> Self { - NodeTag::UNKNOWN + NodeStatus::UNKNOWN } } -impl Default for NodeTag { +impl Default for NodeStatus { fn default() -> Self { - NodeTag::UNKNOWN + NodeStatus::UNKNOWN } } #[derive(Clone, PartialEq, Encode, Decode)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] -pub struct NodeStatus { +pub struct NodeInfo { pub node_key: NodeKey, pub node: Node, } @@ -73,7 +73,7 @@ impl Node { } } - pub fn change_tag(&mut self, new_tag: NodeTag) { + pub fn change_tag(&mut self, new_tag: NodeStatus) { self.node_tag = new_tag; } diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index ab5709c9..9076e6b3 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -1,6 +1,6 @@ //! The public interface to manage Nodes. -use crate::ddc_bucket::node::entity::{NodeStatus, Resource, NodeKey, NodeParams, NodeTag}; +use crate::ddc_bucket::node::entity::{NodeInfo, Resource, NodeKey, NodeParams, NodeStatus}; use crate::ddc_bucket::perm::entity::Permission; use crate::ddc_bucket::{AccountId, Balance, DdcBucket, NodeCreated, Result}; use ink_lang::codegen::{EmitEvent, StaticEnv}; @@ -24,7 +24,7 @@ impl DdcBucket { rent_per_month: Balance, node_params: NodeParams, capacity: Resource, - node_tag: NodeTag, + node_tag: NodeStatus, ) -> Result { let provider_id = Self::env().caller(); @@ -43,7 +43,7 @@ impl DdcBucket { Ok(node_key) } - pub fn message_node_change_tag(&mut self, node_key: NodeKey, new_tag: NodeTag) -> Result<()> { + pub fn message_node_change_tag(&mut self, node_key: NodeKey, new_tag: NodeStatus) -> Result<()> { let caller = Self::env().caller(); let mut node = self.nodes.get(node_key)?; node.only_owner(caller)?; @@ -52,9 +52,9 @@ impl DdcBucket { Ok(()) } - pub fn message_node_get(&self, node_key: NodeKey) -> Result { + pub fn message_node_get(&self, node_key: NodeKey) -> Result { let node = self.nodes.get(node_key)?; - Ok(NodeStatus { + Ok(NodeInfo { node_key, node, }) @@ -79,7 +79,7 @@ impl DdcBucket { offset: u32, limit: u32, filter_provider_id: Option, - ) -> (Vec, u32) { + ) -> (Vec, u32) { let mut nodes = Vec::with_capacity(limit as usize); for idx in offset..offset + limit { let node_key = match self.nodes.keys.get(idx as usize) { @@ -97,7 +97,7 @@ impl DdcBucket { } // Include the complete status of matched items. - let status = NodeStatus { + let status = NodeInfo { node_key, node, }; diff --git a/bucket/ddc_bucket/node/store.rs b/bucket/ddc_bucket/node/store.rs index d3a8e519..95641f12 100644 --- a/bucket/ddc_bucket/node/store.rs +++ b/bucket/ddc_bucket/node/store.rs @@ -7,7 +7,7 @@ use ink_storage::Mapping; // use crate::ddc_bucket::node::entity::Resource; use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; -use super::entity::{Node, NodeTag, NodeKey, NodeParams, Resource}; +use super::entity::{Node, NodeStatus, NodeKey, NodeParams, Resource}; #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(StorageLayout, Debug))] @@ -25,7 +25,7 @@ impl NodeStore { rent_per_month: Balance, node_params: NodeParams, capacity: Resource, - node_tag: NodeTag, + node_tag: NodeStatus, ) -> Result { let node = Node { diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index 51c10acc..86c0de68 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -2,9 +2,9 @@ use ink_lang as ink; use crate::ddc_bucket::account::entity::Account; // use crate::ddc_bucket::cdn_node::entity::CdnNodeKey; -use crate::ddc_bucket::cluster::entity::ClusterStatus; +use crate::ddc_bucket::cluster::entity::ClusterInfo; use crate::ddc_bucket::flow::Flow; -use crate::ddc_bucket::node::entity::{NodeTag, NodeKey}; +use crate::ddc_bucket::node::entity::{NodeStatus, NodeKey}; use crate::ddc_bucket::schedule::{Schedule, MS_PER_MONTH}; use crate::ddc_bucket::Error::*; use crate::ddc_bucket::*; @@ -71,7 +71,7 @@ fn new_cluster() -> TestCluster { rent_per_vnode, node_params0.to_string(), capacity, - NodeTag::ADDING, + NodeStatus::ADDING, ); // Provide another Node. @@ -83,7 +83,7 @@ fn new_cluster() -> TestCluster { rent_per_vnode, node_params1.to_string(), capacity, - NodeTag::ADDING, + NodeStatus::ADDING, ); // Provide another Node. @@ -95,7 +95,7 @@ fn new_cluster() -> TestCluster { rent_per_vnode, node_params2.to_string(), capacity, - NodeTag::ADDING, + NodeStatus::ADDING, ); // Create a Cluster. @@ -315,13 +315,13 @@ fn cluster_create_works() { assert_eq!( node0, - NodeStatus { + NodeInfo { node_key: ctx.node_key0, node: Node { provider_id: ctx.provider_id0, rent_per_month: ctx.rent_per_vnode, free_resource: ctx.capacity - ctx.reserved * 3, - node_tag: NodeTag::ADDING, + node_tag: NodeStatus::ADDING, node_params: ctx.node_params0.to_string(), } } @@ -330,13 +330,13 @@ fn cluster_create_works() { let node1 = ctx.contract.node_get(ctx.node_key1)?; assert_eq!( node1, - NodeStatus { + NodeInfo { node_key: ctx.node_key1, node: Node { provider_id: ctx.provider_id1, rent_per_month: ctx.rent_per_vnode, free_resource: ctx.capacity - ctx.reserved * 3, - node_tag: NodeTag::ADDING, + node_tag: NodeStatus::ADDING, node_params: ctx.node_params1.to_string(), } } @@ -345,13 +345,13 @@ fn cluster_create_works() { let node2 = ctx.contract.node_get(ctx.node_key2)?; assert_eq!( node2, - NodeStatus { + NodeInfo { node_key: ctx.node_key2, node: Node { provider_id: ctx.provider_id2, rent_per_month: ctx.rent_per_vnode, free_resource: ctx.capacity - ctx.reserved * 3, - node_tag: NodeTag::ADDING, + node_tag: NodeStatus::ADDING, node_params: ctx.node_params2.to_string(), } } @@ -363,7 +363,7 @@ fn cluster_create_works() { let cluster = ctx.contract.cluster_get(ctx.cluster_id)?; assert_eq!( cluster, - ClusterStatus { + ClusterInfo { cluster_id: ctx.cluster_id, cluster: Cluster { manager_id: ctx.manager, @@ -807,7 +807,7 @@ fn cluster_add_node() { let rent_per_month = 100; let node_params = "new_node"; let capacity = 1000; - let node_tag = NodeTag::ACTIVE; + let node_tag = NodeStatus::ACTIVE; set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); let new_node_id = ctx.contract.node_create( @@ -968,7 +968,7 @@ fn bucket_reserve_0_works() { assert_eq!( contract.cluster_list(0, 10, None), ( - vec![ClusterStatus { + vec![ClusterInfo { cluster_id: 0, cluster: Cluster { manager_id: AccountId::default(), @@ -988,13 +988,13 @@ fn bucket_reserve_0_works() { assert_eq!( contract.node_list(0, 10, None), ( - vec![NodeStatus { + vec![NodeInfo { node_key: AccountId::default(), node: Node { provider_id: AccountId::default(), rent_per_month: 0, free_resource: 0, - node_tag: NodeTag::ACTIVE, + node_tag: NodeStatus::ACTIVE, node_params: "".to_string(), } }], @@ -1315,7 +1315,7 @@ fn node_list_works() { rent_per_month, node_params1.to_string(), capacity, - NodeTag::ADDING, + NodeStatus::ADDING, ); let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; @@ -1325,7 +1325,7 @@ fn node_list_works() { rent_per_month, node_params2.to_string(), capacity, - NodeTag::ADDING, + NodeStatus::ADDING, ); let node_status = ddc_bucket.node_get(AccountId::from([0x0b; 32])).unwrap(); @@ -1334,24 +1334,24 @@ fn node_list_works() { assert_ne!(node_key1, node_key2); let count = 3; - let node1 = NodeStatus { + let node1 = NodeInfo { node_key: node_key1, node: Node { provider_id: owner_id1, rent_per_month, free_resource: capacity, - node_tag: NodeTag::ADDING, + node_tag: NodeStatus::ADDING, node_params: node_params1.to_string(), }, }; - let node2 = NodeStatus { + let node2 = NodeInfo { node_key: node_key2, node: Node { provider_id: owner_id2, rent_per_month, free_resource: capacity, - node_tag: NodeTag::ADDING, + node_tag: NodeStatus::ADDING, node_params: node_params2.to_string(), }, }; diff --git a/bucket/lib.rs b/bucket/lib.rs index 16a192e3..e8700f12 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -2,7 +2,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![feature(proc_macro_hygiene)] // for tests in a separate file -#![deny(unused_must_use, unused_variables)] +// #![deny(unused_must_use, unused_variables)] use ink_lang as ink; @@ -31,7 +31,7 @@ pub mod ddc_bucket { use self::buckets_perms::store::BucketsPermsStore; use self::cdn_cluster::store::CdnClusterStore; - use self::cdn_node::entity::{CdnNodeStatus, CdnNodeKey, CdnNodeParams}; + use self::cdn_node::entity::{CdnNodeInfo, CdnNodeKey, CdnNodeParams}; use self::protocol::store::ProtocolStore; use self::topology::store::TopologyStore; @@ -104,7 +104,7 @@ pub mod ddc_bucket { 0, "".to_string(), 0, - NodeTag::ACTIVE, + NodeStatus::ACTIVE, ) .unwrap(); let _ = contract @@ -167,148 +167,148 @@ pub mod ddc_bucket { } impl DdcBucket { - /// Create a new bucket and return its `bucket_id`. - /// - /// The caller will be its first owner and payer of resources. - /// - /// `bucket_params` is configuration used by clients and nodes. See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema) - /// - /// The bucket can be connected to a single cluster (currently). Allocate cluster resources with the function `bucket_alloc_into_cluster` - #[ink(message, payable)] - pub fn bucket_create( - &mut self, - bucket_params: BucketParams, - cluster_id: ClusterId, - owner_id: Option, - ) -> BucketId { - self.message_bucket_create(bucket_params, cluster_id, owner_id) - .unwrap() - } - - /// Change owner of the bucket - /// - /// Provide the account of new owner - #[ink(message, payable)] - pub fn bucket_change_owner(&mut self, bucket_id: BucketId, owner_id: AccountId) -> () { - self.message_bucket_change_owner(bucket_id, owner_id) - .unwrap() - } - - /// Allocate some resources of a cluster to a bucket. - /// - /// The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes). - #[ink(message)] - pub fn bucket_alloc_into_cluster(&mut self, bucket_id: BucketId, resource: Resource) -> () { - self.message_bucket_alloc_into_cluster(bucket_id, resource) - .unwrap() - } - - /// Settle the due costs of a bucket from its payer account to the cluster account. - #[ink(message)] - pub fn bucket_settle_payment(&mut self, bucket_id: BucketId) { - self.message_bucket_settle_payment(bucket_id).unwrap() - } - - /// Change the `bucket_params`, which is configuration used by clients and nodes. - /// - /// See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema) - #[ink(message, payable)] - pub fn bucket_change_params(&mut self, bucket_id: BucketId, params: BucketParams) { - self.message_bucket_change_params(bucket_id, params) - .unwrap(); - } - - /// Get the current status of a bucket. - #[ink(message)] - pub fn bucket_get(&self, bucket_id: BucketId) -> Result { - self.message_bucket_get(bucket_id) - } - - /// Iterate through all buckets. - /// - /// The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`. - /// The optimal `limit` depends on the size of params. - /// - /// The results can be filtered by owner. Note that paging must still be completed fully. - #[ink(message)] - pub fn bucket_list( - &self, - offset: u32, - limit: u32, - filter_owner_id: Option, - ) -> (Vec, u32) { - self.message_bucket_list(offset, limit, filter_owner_id) - } - - /// Iterate through all buckets and return only those owned by owner - /// - /// This method returns bucket struct, not the status - #[ink(message)] - pub fn bucket_list_for_account(&self, owner_id: AccountId) -> Vec { - self.message_bucket_list_for_account(owner_id) - } - - /// Set availiablity of the bucket - #[ink(message)] - pub fn bucket_set_availability( - &mut self, - bucket_id: BucketId, - public_availability: bool, - ) -> () { - self.message_bucket_set_availability(bucket_id, public_availability) - .unwrap() - } - - /// Set max resource cap to be charged by CDN for public bucket - #[ink(message)] - pub fn bucket_set_resource_cap( - &mut self, - bucket_id: BucketId, - new_resource_cap: Resource, - ) -> () { - self.message_bucket_set_resource_cap(bucket_id, new_resource_cap) - .unwrap() - } - - /// Set permission for the reader of the bucket - #[ink(message)] - pub fn get_bucket_writers(&mut self, bucket_id: BucketId) -> Vec { - self.message_get_bucket_writers(bucket_id).unwrap() - } - - /// Set permission for the writer of the bucket - #[ink(message)] - pub fn bucket_set_writer_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { - self.message_grant_writer_permission(bucket_id, writer) - .unwrap() - } - - /// Revoke permission for the writer of the bucket - #[ink(message)] - pub fn bucket_revoke_writer_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { - self.message_revoke_writer_permission(bucket_id, writer) - .unwrap() - } - - /// Set permission for the reader of the bucket - #[ink(message)] - pub fn get_bucket_readers(&mut self, bucket_id: BucketId) -> Vec { - self.message_get_bucket_readers(bucket_id).unwrap() - } - - /// Set permission for the reader of the bucket - #[ink(message)] - pub fn bucket_set_reader_perm(&mut self, bucket_id: BucketId, reader: AccountId) -> () { - self.message_grant_reader_permission(bucket_id, reader) - .unwrap() - } - - /// Revoke permission for the reader of the bucket - #[ink(message)] - pub fn bucket_revoke_reader_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { - self.message_revoke_reader_permission(bucket_id, writer) - .unwrap() - } + // /// Create a new bucket and return its `bucket_id`. + // /// + // /// The caller will be its first owner and payer of resources. + // /// + // /// `bucket_params` is configuration used by clients and nodes. See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema) + // /// + // /// The bucket can be connected to a single cluster (currently). Allocate cluster resources with the function `bucket_alloc_into_cluster` + // #[ink(message, payable)] + // pub fn bucket_create( + // &mut self, + // bucket_params: BucketParams, + // cluster_id: ClusterId, + // owner_id: Option, + // ) -> BucketId { + // self.message_bucket_create(bucket_params, cluster_id, owner_id) + // .unwrap() + // } + + // /// Change owner of the bucket + // /// + // /// Provide the account of new owner + // #[ink(message, payable)] + // pub fn bucket_change_owner(&mut self, bucket_id: BucketId, owner_id: AccountId) -> () { + // self.message_bucket_change_owner(bucket_id, owner_id) + // .unwrap() + // } + + // /// Allocate some resources of a cluster to a bucket. + // /// + // /// The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes). + // #[ink(message)] + // pub fn bucket_alloc_into_cluster(&mut self, bucket_id: BucketId, resource: Resource) -> () { + // self.message_bucket_alloc_into_cluster(bucket_id, resource) + // .unwrap() + // } + + // /// Settle the due costs of a bucket from its payer account to the cluster account. + // #[ink(message)] + // pub fn bucket_settle_payment(&mut self, bucket_id: BucketId) { + // self.message_bucket_settle_payment(bucket_id).unwrap() + // } + + // /// Change the `bucket_params`, which is configuration used by clients and nodes. + // /// + // /// See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema) + // #[ink(message, payable)] + // pub fn bucket_change_params(&mut self, bucket_id: BucketId, params: BucketParams) { + // self.message_bucket_change_params(bucket_id, params) + // .unwrap(); + // } + + // /// Get the current status of a bucket. + // #[ink(message)] + // pub fn bucket_get(&self, bucket_id: BucketId) -> Result { + // self.message_bucket_get(bucket_id) + // } + + // /// Iterate through all buckets. + // /// + // /// The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`. + // /// The optimal `limit` depends on the size of params. + // /// + // /// The results can be filtered by owner. Note that paging must still be completed fully. + // #[ink(message)] + // pub fn bucket_list( + // &self, + // offset: u32, + // limit: u32, + // filter_owner_id: Option, + // ) -> (Vec, u32) { + // self.message_bucket_list(offset, limit, filter_owner_id) + // } + + // /// Iterate through all buckets and return only those owned by owner + // /// + // /// This method returns bucket struct, not the status + // #[ink(message)] + // pub fn bucket_list_for_account(&self, owner_id: AccountId) -> Vec { + // self.message_bucket_list_for_account(owner_id) + // } + + // /// Set availiablity of the bucket + // #[ink(message)] + // pub fn bucket_set_availability( + // &mut self, + // bucket_id: BucketId, + // public_availability: bool, + // ) -> () { + // self.message_bucket_set_availability(bucket_id, public_availability) + // .unwrap() + // } + + // /// Set max resource cap to be charged by CDN for public bucket + // #[ink(message)] + // pub fn bucket_set_resource_cap( + // &mut self, + // bucket_id: BucketId, + // new_resource_cap: Resource, + // ) -> () { + // self.message_bucket_set_resource_cap(bucket_id, new_resource_cap) + // .unwrap() + // } + + // /// Set permission for the reader of the bucket + // #[ink(message)] + // pub fn get_bucket_writers(&mut self, bucket_id: BucketId) -> Vec { + // self.message_get_bucket_writers(bucket_id).unwrap() + // } + + // /// Set permission for the writer of the bucket + // #[ink(message)] + // pub fn bucket_set_writer_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { + // self.message_grant_writer_permission(bucket_id, writer) + // .unwrap() + // } + + // /// Revoke permission for the writer of the bucket + // #[ink(message)] + // pub fn bucket_revoke_writer_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { + // self.message_revoke_writer_permission(bucket_id, writer) + // .unwrap() + // } + + // /// Set permission for the reader of the bucket + // #[ink(message)] + // pub fn get_bucket_readers(&mut self, bucket_id: BucketId) -> Vec { + // self.message_get_bucket_readers(bucket_id).unwrap() + // } + + // /// Set permission for the reader of the bucket + // #[ink(message)] + // pub fn bucket_set_reader_perm(&mut self, bucket_id: BucketId, reader: AccountId) -> () { + // self.message_grant_reader_permission(bucket_id, reader) + // .unwrap() + // } + + // /// Revoke permission for the reader of the bucket + // #[ink(message)] + // pub fn bucket_revoke_reader_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { + // self.message_revoke_reader_permission(bucket_id, writer) + // .unwrap() + // } } // ---- End Bucket ---- @@ -355,21 +355,67 @@ pub mod ddc_bucket { } impl DdcBucket { + + /// Creates a cluster of Storage nodes and CDN nodes. + /// + /// This endpoint creates a cluster of Storage nodes and CDN nodes with specific parameters. + /// The caller will be the cluster owner (cluster manager). In order to add a Storage or CDN node, the manager must be authorized by the node owner using the `trust_manager` endpoint. + /// + /// # Parameters + /// + /// * `nodes_keys` - Public Keys of Storage nodes that are being added to the cluster. This param can accept up to 10 nodes per call. + /// * `v_nodes` - List of tokens (positions) related to Storage nodes from the `nodes_keys` param. The index of associated physical Storage node must be aligned with its virtual nodes list index. + /// * `cdn_nodes_keys` - Public Keys of Storage CDN that are being added to the cluster. This param can accept up to 10 nodes per call. + /// * `cluster_params` - [Cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. + /// + /// # Output + /// + /// Returns ID of the created cluster. + /// + /// # Errors + /// + /// Returns `ClusterManagerIsNotTrusted` error if the caller has a lack of trusted manager permissions for nodes he is trying to add. + /// Returns `NodeDoesNotExist` error if the adding Storage node does not exist. + /// Returns `InvalidVirtualNodes` error if there is a mismatch between adding Storage nodes and its virtual nodes. + /// Returns `CdnNodeDoesNotExist` error if the adding CDN node does not exist. + /// Returns `NodeIsAlreadyAddedToCluster(cluster_id)` error if an adding Storage node is already added to this or another cluster. + /// Returns `CdnNodeIsAlreadyAddedToCluster(cluster_id)` error if an adding CDN node is already added to this or another cluster. + #[ink(message, payable)] + pub fn cluster_create( + &mut self, + nodes_keys: Vec, + v_nodes: Vec>, + cdn_nodes_keys: Vec, + cluster_params: ClusterParams, + ) -> ClusterId { + // self.message_cluster_create(nodes_keys, v_nodes, cdn_nodes_keys, cluster_params) + // .unwrap() + 1u32 + } + /// Adds a Storage node to the targeting cluster. /// /// This endpoint adds a physical Storage node along with its virtual nodes to the targeting cluster. - /// The node will be added to the end of the cluster nodes list. /// Virtual nodes determines a token (position) on the ring in terms of Consistent Hashing. + /// The Storage node can be added to the cluster by cluster manager only. + /// + /// # Parameters + /// + /// * `cluster_id` - ID of the targeting cluster. + /// * `node_key` - Public Key associated with the Storage node. + /// * `v_nodes` - List of tokens (positions) related to the Storage node. /// - /// # Arguments + /// # Output /// - /// * `cluster_id` - ID of the targeting cluster - /// * `node_key` - Public Key associated with the Storage node - /// * `v_nodes` - List of tokens (positions) related to the Storage node + /// Returns nothing. /// /// # Errors /// - /// This endpoint will return `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// Returns `ClusterDoesNotExist` error if the cluster does not exist. + /// Returns `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// Returns `NodeDoesNotExist` error if the adding Storage node does not exist. + /// Returns `NodeIsAlreadyAddedToCluster(cluster_id)` error if the adding Storage node is already added to this or another cluster. #[ink(message, payable)] pub fn cluster_add_node( &mut self, @@ -377,117 +423,286 @@ pub mod ddc_bucket { node_key: NodeKey, v_nodes: Vec, ) { - self.message_cluster_add_node(cluster_id, node_key, v_nodes) - .unwrap() + // self.message_cluster_add_node(cluster_id, node_key, v_nodes) + // .unwrap() } /// Removes a Storage node from the targeting cluster. /// /// This endpoint removes a physical Storage node along with its virtual nodes from the targeting cluster. + /// The Storage node can be removed from the cluster either by cluster manager or by the node owner. + /// + /// # Parameters /// - /// # Arguments + /// * `cluster_id` - ID of the targeting cluster. + /// * `node_key` - Public Key associated with the Storage node. /// - /// * `cluster_id` - ID of the targeting cluster - /// * `node_key` - Public Key associated with the Storage node + /// # Output + /// + /// Returns nothing. /// /// # Errors /// - /// This endpoint will return `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. - #[ink(message, payable)] + /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// Returns `ClusterDoesNotExist` error if the cluster does not exist. + /// Returns `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// Returns `NodeDoesNotExist` error if the removing Storage node does not exist. + /// Returns `NodeIsNotInCluster(cluster_id)` error if the removing Storage node is not in this cluster. + #[ink(message)] pub fn cluster_remove_node( &mut self, cluster_id: ClusterId, node_key: NodeKey, ) { - self.message_cluster_remove_node(cluster_id, node_key) - .unwrap() + // self.message_cluster_remove_node(cluster_id, node_key) + // .unwrap() } - /// Creates a new cluster and returns its `cluster_id`. + /// Adds a CDN node to the targeting cluster. + /// + /// This endpoint adds a CDN node to the targeting cluster. + /// The CDN node can be added to the cluster by cluster manager only. /// - /// The caller will be its first manager. + /// # Parameters /// - /// The cluster can contain both Storage and CDN nodes. The `v_nodes` are assigned to the given Storage physical nodes in a round-robin. Only nodes of providers that trust the cluster manager can be used (see `node_trust_manager`). The assignment can be changed with the function `cluster_replace_node`. + /// * `cluster_id` - ID of the targeting cluster. + /// * `cdn_node_key` - Public Key associated with the CDN node. /// - /// `cluster_params` is configuration used by clients and nodes. In particular, this describes the semantics of vnodes. See the [data structure of ClusterParams](https://docs.cere.network/ddc/protocols/contract-params-schema) + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// Returns `ClusterDoesNotExist` error if the cluster does not exist. + /// Returns `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// Returns `CdnNodeDoesNotExist` error if the adding CDN node does not exist. + /// Returns `CdnNodeIsAlreadyAddedToCluster(cluster_id)` error if the adding CDN node is already added to this or another cluster. #[ink(message, payable)] - pub fn cluster_create( + pub fn cluster_add_cdn_node( &mut self, - nodes_keys: Vec, - v_nodes: Vec>, - cdn_nodes_keys: Vec, - cluster_params: ClusterParams, - ) -> ClusterId { - self.message_cluster_create(nodes_keys, v_nodes, cdn_nodes_keys, cluster_params) - .unwrap() + cluster_id: ClusterId, + cdn_node_key: CdnNodeKey, + ) { + } - /// As manager, reserve more resources for the cluster from the free capacity of nodes. + /// Removes a CDN node from the targeting cluster. + /// + /// This endpoint removes a CDN node the targeting cluster. + /// The CDN node can be removed from the cluster either by cluster manager or by the node owner. + /// + /// # Parameters + /// + /// * `cluster_id` - ID of the targeting cluster. + /// * `cdn_node_key` - Public Key associated with the CDN node. + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Errors /// - /// The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes). + /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// Returns `ClusterDoesNotExist` error if the cluster does not exist. + /// Returns `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// Returns `CdnNodeDoesNotExist` error if the removing CDN node does not exist. + /// Returns `CdnNodeIsNotInCluster(cluster_id)` error if the removing CDN node is not in this cluster. #[ink(message)] - pub fn cluster_reserve_resource(&mut self, cluster_id: ClusterId, amount: Resource) -> () { - self.message_cluster_reserve_resource(cluster_id, amount) - .unwrap() + pub fn cluster_remove_cdn_node( + &mut self, + cluster_id: ClusterId, + cdn_node_key: CdnNodeKey, + ) { + } - /// As manager, change a node tag - #[ink(message)] - pub fn cluster_change_node_tag(&mut self, node_key: NodeKey, new_tag: NodeTag) -> () { - self.message_node_change_tag(node_key, new_tag).unwrap() + /// Changes parameters for the targeting cluster. + /// + /// This enpoint updates [cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. + /// All cluster parameters must be specified as the endpoint works using SET approach. + /// + /// # Parameters + /// + /// * `cluster_id` - ID of the targeting cluster. + /// * `cluster_params` - [Cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// Returns `ClusterDoesNotExist` error if the cluster does not exist. + #[ink(message, payable)] + pub fn cluster_change_params( + &mut self, + cluster_id: ClusterId, + cluster_params: ClusterParams + ) { + self.message_cluster_change_params(cluster_id, cluster_params) + .unwrap(); } - /// As manager, re-assign a vnode to another physical node. + /// Removes a cluster. + /// + /// This enpoint removes the cluster if it does not contain any nodes. + /// Only an empty cluster can be removed. + /// + /// # Parameters + /// + /// * `cluster_id` - ID of the targeting cluster. /// - /// The cluster manager can only use nodes of providers that trust him (see `node_trust_manager`), or any nodes if he is also SuperAdmin. + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// Returns `ClusterDoesNotExist` error if the cluster does not exist. + /// Returns `ClusterIsNotEmpty` error if the removing cluster contains some Storage or CDN nodes. #[ink(message)] - pub fn cluster_replace_node( - &mut self, - cluster_id: ClusterId, - v_nodes: Vec, - new_node_key: NodeKey, - ) -> () { - self.message_cluster_replace_node(cluster_id, v_nodes, new_node_key) - .unwrap() + pub fn cluster_remove( + &mut self, + cluster_id: ClusterId, + ) { + } - /// Trigger the distribution of revenues from the cluster to the providers. + /// Changes Storage node status. + /// + /// This enpoint changes Storage node status in a cluster. + /// + /// # Parameters + /// + /// * `node_key` - Public Key associated with the Storage node. + /// * `status` - Status for the targeting Storage node, can be one of the following: ACTIVE, ADDING, DELETING, OFFLINE. + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// Returns `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. #[ink(message)] - pub fn cluster_distribute_revenues(&mut self, cluster_id: ClusterId) { - self.message_cluster_distribute_revenues(cluster_id) - .unwrap() + pub fn cluster_set_node_status( + &mut self, + node_key: NodeKey, + status: NodeStatus + ) { + self.message_node_change_tag(node_key, status).unwrap(); } - /// Change the `cluster_params`, which is configuration used by clients and nodes. + /// Changes CDN node status. /// - /// See the [data structure of ClusterParams](https://docs.cere.network/ddc/protocols/contract-params-schema) - #[ink(message, payable)] - pub fn cluster_change_params(&mut self, cluster_id: ClusterId, params: ClusterParams) { - self.message_cluster_change_params(cluster_id, params) - .unwrap(); + /// This enpoint changes CDN node status in a cluster. + /// + /// # Parameters + /// + /// * `cdn_node_key` - Public Key associated with the CDN node. + /// * `status` - Status for the targeting CDN node, can be one of the following: ACTIVE, ADDING, DELETING, OFFLINE. + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// Returns `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + #[ink(message)] + pub fn cluster_set_cdn_node_status( + &mut self, + cdn_node_key: NodeKey, + status: NodeStatus + ) { } - /// Get the current status of a cluster. + /// Gets a cluster. + /// + /// This enpoint gets the targeting cluster along with its parameters, Storage and CDN nodes. + /// + /// # Parameters + /// + /// * `cluster_id` - ID of the targeting cluster. + /// + /// # Output + /// + /// Returns `ClusterInfo` data transfer object. + /// + /// # Errors + /// + /// Returns `ClusterDoesNotExist` error if the cluster does not exist. #[ink(message)] - pub fn cluster_get(&self, cluster_id: ClusterId) -> Result { + pub fn cluster_get( + &self, + cluster_id: ClusterId + ) -> Result { self.message_cluster_get(cluster_id) } - /// Iterate through all clusters. + /// Gets a paginated list of clusters. /// + /// This enpoint gets a paginated list of clusters along with their parameters, Storage and CDN nodes. /// The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`. /// The optimal `limit` depends on the size of params. /// - /// The results can be filtered by manager. Note that paging must still be completed fully. + /// # Parameters + /// + /// * `offset` - starting offset. + /// * `limit` - page limit. + /// * `filter_manager_id` - optional filter by cluster manager. + /// + /// # Errors + /// + /// No errors. In case a pagination param is out of bounds, an empty list will be returned. #[ink(message)] pub fn cluster_list( &self, offset: u32, limit: u32, filter_manager_id: Option, - ) -> (Vec, u32) { + ) -> (Vec, u32) { self.message_cluster_list(offset, limit, filter_manager_id) } + + + + // /// As manager, reserve more resources for the cluster from the free capacity of nodes. + // /// + // /// The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes). + // #[ink(message)] + // pub fn cluster_reserve_resource(&mut self, cluster_id: ClusterId, amount: Resource) -> () { + // self.message_cluster_reserve_resource(cluster_id, amount) + // .unwrap() + // } + + // /// As manager, re-assign a vnode to another physical node. + // /// + // /// The cluster manager can only use nodes of providers that trust him (see `node_trust_manager`), or any nodes if he is also SuperAdmin. + // #[ink(message)] + // pub fn cluster_replace_node( + // &mut self, + // cluster_id: ClusterId, + // v_nodes: Vec, + // new_node_key: NodeKey, + // ) -> () { + // self.message_cluster_replace_node(cluster_id, v_nodes, new_node_key) + // .unwrap() + // } + + // /// Trigger the distribution of revenues from the cluster to the providers. + // #[ink(message)] + // pub fn cluster_distribute_revenues(&mut self, cluster_id: ClusterId) { + // self.message_cluster_distribute_revenues(cluster_id) + // .unwrap() + // } + } // ---- End Cluster ---- @@ -514,123 +729,123 @@ pub mod ddc_bucket { } impl DdcBucket { - /// Create a new cluster and return its `cluster_id`. - /// - /// The caller will be its first manager. - /// - /// The CDN node ids are provided, which will form a cluster. - #[ink(message, payable)] - pub fn cdn_cluster_create(&mut self, cdn_node_keys: Vec) -> ClusterId { - self.message_cdn_cluster_create(cdn_node_keys).unwrap() - } - - /// Set rate for streaming (price per gb) - #[ink(message, payable)] - pub fn cdn_set_rate(&mut self, cluster_id: ClusterId, usd_per_gb: Balance) -> () { - self.message_cdn_set_rate(cluster_id, usd_per_gb).unwrap() - } - - /// Get rate for streaming (price per gb) - #[ink(message, payable)] - pub fn cdn_get_rate(&self, cluster_id: ClusterId) -> Balance { - self.message_cdn_get_rate(cluster_id).unwrap() - } - - /// As validator, charge payments from users and allocate undistributed payments to CDN nodes. - /// - /// As a result CDN cluster revenue increases, which can be distributed between CDN node providers via method cdn_cluster_distribute_revenues. - #[ink(message)] - pub fn cdn_cluster_put_revenue( - &mut self, - cluster_id: ClusterId, - aggregates_accounts: Vec<(AccountId, u128)>, - aggregates_nodes: Vec<(CdnNodeKey, u128)>, - aggregates_buckets: Vec<(BucketId, Resource)>, - era: u64, - ) -> () { - self.message_cdn_cluster_put_revenue( - cluster_id, - aggregates_accounts, - aggregates_nodes, - aggregates_buckets, - era, - ) - .unwrap() - } - - /// Trigger the distribution of revenues from the cluster to the CDN node providers. - /// - /// Anyone can call this method. - /// - /// Undistributed payments will be trasnferred, CDN cluster revenue will decrease. - #[ink(message)] - pub fn cdn_cluster_distribute_revenues(&mut self, cluster_id: ClusterId) { - self.message_cdn_cluster_distribute_revenues(cluster_id) - .unwrap() - } - - /// Get the current status of a cluster. - #[ink(message)] - pub fn cdn_cluster_get(&self, cluster_id: ClusterId) -> Result { - self.message_cdn_cluster_get(cluster_id) - } - - /// Iterate through all clusters. - /// - /// The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`. - /// The optimal `limit` depends on the size of params. - /// - /// The results can be filtered by manager. Note that paging must still be completed fully. - #[ink(message)] - pub fn cdn_cluster_list( - &self, - offset: u32, - limit: u32, - filter_manager_id: Option, - ) -> (Vec, u32) { - self.message_cdn_cluster_list(offset, limit, filter_manager_id) - } + // /// Create a new cluster and return its `cluster_id`. + // /// + // /// The caller will be its first manager. + // /// + // /// The CDN node ids are provided, which will form a cluster. + // #[ink(message, payable)] + // pub fn cdn_cluster_create(&mut self, cdn_node_keys: Vec) -> ClusterId { + // self.message_cdn_cluster_create(cdn_node_keys).unwrap() + // } + + // /// Set rate for streaming (price per gb) + // #[ink(message, payable)] + // pub fn cdn_set_rate(&mut self, cluster_id: ClusterId, usd_per_gb: Balance) -> () { + // self.message_cdn_set_rate(cluster_id, usd_per_gb).unwrap() + // } + + // /// Get rate for streaming (price per gb) + // #[ink(message, payable)] + // pub fn cdn_get_rate(&self, cluster_id: ClusterId) -> Balance { + // self.message_cdn_get_rate(cluster_id).unwrap() + // } + + // /// As validator, charge payments from users and allocate undistributed payments to CDN nodes. + // /// + // /// As a result CDN cluster revenue increases, which can be distributed between CDN node providers via method cdn_cluster_distribute_revenues. + // #[ink(message)] + // pub fn cdn_cluster_put_revenue( + // &mut self, + // cluster_id: ClusterId, + // aggregates_accounts: Vec<(AccountId, u128)>, + // aggregates_nodes: Vec<(CdnNodeKey, u128)>, + // aggregates_buckets: Vec<(BucketId, Resource)>, + // era: u64, + // ) -> () { + // self.message_cdn_cluster_put_revenue( + // cluster_id, + // aggregates_accounts, + // aggregates_nodes, + // aggregates_buckets, + // era, + // ) + // .unwrap() + // } + + // /// Trigger the distribution of revenues from the cluster to the CDN node providers. + // /// + // /// Anyone can call this method. + // /// + // /// Undistributed payments will be trasnferred, CDN cluster revenue will decrease. + // #[ink(message)] + // pub fn cdn_cluster_distribute_revenues(&mut self, cluster_id: ClusterId) { + // self.message_cdn_cluster_distribute_revenues(cluster_id) + // .unwrap() + // } + + // /// Get the current status of a cluster. + // #[ink(message)] + // pub fn cdn_cluster_get(&self, cluster_id: ClusterId) -> Result { + // self.message_cdn_cluster_get(cluster_id) + // } + + // /// Iterate through all clusters. + // /// + // /// The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`. + // /// The optimal `limit` depends on the size of params. + // /// + // /// The results can be filtered by manager. Note that paging must still be completed fully. + // #[ink(message)] + // pub fn cdn_cluster_list( + // &self, + // offset: u32, + // limit: u32, + // filter_manager_id: Option, + // ) -> (Vec, u32) { + // self.message_cdn_cluster_list(offset, limit, filter_manager_id) + // } } // ---- End CDN Cluster ---- // ---- Committer ---- impl DdcBucket { - /// CDN node operator sets the commit for current era. - #[ink(message)] - pub fn set_commit(&mut self, cdn_owner: AccountId, cdn_node_key: CdnNodeKey, commit: Commit) { - self.message_set_commit(cdn_owner, cdn_node_key, commit); - } - - /// Return the last commit submitted by CDN node operator - #[ink(message)] - pub fn get_commit(&self, cdn_owner: AccountId) -> Vec<(CdnNodeKey, Commit)> { - self.message_get_commit(cdn_owner) - } - - /// Return last era validated per CDN node - #[ink(message)] - pub fn get_validated_commit(&self, cdn_node_key: CdnNodeKey) -> EraAndTimestamp { - self.message_get_validated_commit(cdn_node_key) - } - - /// Set the new configs for era - #[ink(message)] - pub fn set_era(&mut self, era_config: EraConfig) -> () { - self.message_set_era(era_config).unwrap(); - } - - /// Return current status of an era - #[ink(message)] - pub fn get_era(&self) -> EraStatus { - self.message_get_era() - } - - /// Return current era settings - #[ink(message)] - pub fn get_era_settings(&self) -> EraConfig { - self.message_get_era_settings() - } + // /// CDN node operator sets the commit for current era. + // #[ink(message)] + // pub fn set_commit(&mut self, cdn_owner: AccountId, cdn_node_key: CdnNodeKey, commit: Commit) { + // self.message_set_commit(cdn_owner, cdn_node_key, commit); + // } + + // /// Return the last commit submitted by CDN node operator + // #[ink(message)] + // pub fn get_commit(&self, cdn_owner: AccountId) -> Vec<(CdnNodeKey, Commit)> { + // self.message_get_commit(cdn_owner) + // } + + // /// Return last era validated per CDN node + // #[ink(message)] + // pub fn get_validated_commit(&self, cdn_node_key: CdnNodeKey) -> EraAndTimestamp { + // self.message_get_validated_commit(cdn_node_key) + // } + + // /// Set the new configs for era + // #[ink(message)] + // pub fn set_era(&mut self, era_config: EraConfig) -> () { + // self.message_set_era(era_config).unwrap(); + // } + + // /// Return current status of an era + // #[ink(message)] + // pub fn get_era(&self) -> EraStatus { + // self.message_get_era() + // } + + // /// Return current era settings + // #[ink(message)] + // pub fn get_era_settings(&self) -> EraConfig { + // self.message_get_era_settings() + // } } // ---- End Committer ---- @@ -649,68 +864,147 @@ pub mod ddc_bucket { } impl DdcBucket { - /// As node provider, authorize a cluster manager to use his nodes. + // /// As node provider, authorize a cluster manager to use his nodes. + // #[ink(message, payable)] + // pub fn cdn_node_trust_manager(&mut self, manager: AccountId) { + // self.message_cdn_node_trust_manager(manager, true).unwrap(); + // } + + // /// As node provider, revoke the authorization of a cluster manager to use his nodes. + // #[ink(message)] + // pub fn cdn_node_distrust_manager(&mut self, manager: AccountId) { + // self.message_cdn_node_trust_manager(manager, false).unwrap(); + // } + + /// Creates a CDN node + /// + /// This endpoint creates a CDN node with specific parameters. + /// The caller will be the node owner (node provider). + /// + /// # Parameters + /// + /// * `cdn_node_key` - Public Keys of the CDN node that should be treated as node identifier. + /// * `cdn_node_params` - [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. + /// + /// # Output + /// + /// Returns Public Key of the created CDN node. + /// + /// # Errors + /// + /// Returns `CdnNodeAlreadyExists` error if a CDN node with the same Public Key is already created. + /// Returns `InvalidParams(message)` error if there is some invalid configuration parameter. #[ink(message, payable)] - pub fn cdn_node_trust_manager(&mut self, manager: AccountId) { - self.message_cdn_node_trust_manager(manager, true).unwrap(); + pub fn cdn_node_create( + &mut self, + cdn_node_key: CdnNodeKey, + cdn_node_params: CdnNodeParams + ) -> CdnNodeKey { + self.message_cdn_node_create(cdn_node_key, cdn_node_params).unwrap() } - /// As node provider, revoke the authorization of a cluster manager to use his nodes. + /// Removes a CDN node. + /// + /// This enpoint removes the targeting CDN Node if it is not added to some cluster. + /// Only a node that is not a member of some cluster can be removed. + /// + /// # Parameters + /// + /// * `cdn_node_key` - Public Key associated with the CDN node. + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// Returns `UnauthorizedCdnNodeOwner` error if the caller is not the CDN node owner. + /// Returns `CdnNodeDoesNotExist` error if the CDN node does not exist. + /// Returns `CdnNodeIsAddedToCluster(cluster_id)` error if the removing CDN node is added to some cluster. #[ink(message)] - pub fn cdn_node_distrust_manager(&mut self, manager: AccountId) { - self.message_cdn_node_trust_manager(manager, false).unwrap(); + pub fn cdn_node_remove( + &mut self, + cdn_node_key: CdnNodeKey + ) { + self.message_remove_cdn_node(cdn_node_key).unwrap(); } - /// Create a new node and return its `node_id`. + /// Changes parameters for the targeting CDN node. /// - /// The caller will be its owner. + /// This enpoint updates [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. + /// All CDN node parameters must be specified as the endpoint works using SET approach. /// - /// `node_params` is configuration used by clients and nodes. In particular, this contains the URL to the service. See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema) - #[ink(message, payable)] - pub fn cdn_node_create(&mut self, cdn_node_key: CdnNodeKey, cdn_node_params: CdnNodeParams) -> CdnNodeKey { - self.message_cdn_node_create(cdn_node_key, cdn_node_params).unwrap() - } - - /// Change the `node_params`, which is configuration used by clients and nodes. + /// # Parameters + /// + /// * `cdn_node_key` - Public Key associated with the CDN node. + /// * `cdn_node_params` - [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. /// - /// See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema) + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// Returns `UnauthorizedCdnNodeOwner` error if the caller is not the CDN node owner. + /// Returns `CdnNodeDoesNotExist` error if the CDN node does not exist. #[ink(message, payable)] - pub fn cdn_node_change_params(&mut self, cdn_node_key: CdnNodeKey, cdn_node_params: CdnNodeParams) { + pub fn cdn_node_change_params( + &mut self, + cdn_node_key: CdnNodeKey, + cdn_node_params: CdnNodeParams + ) { self.message_cdn_node_change_params(cdn_node_key, cdn_node_params) .unwrap(); } - /// Get the current state of the cdn node + /// Gets a CDN node. + /// + /// This enpoint gets the targeting CDN node along with its parameters. + /// + /// # Parameters + /// + /// * `cdn_node_key` - Public Key associated with the CDN node. + /// + /// # Output + /// + /// Returns `CdnNodeInfo` data transfer object. + /// + /// # Errors + /// + /// Returns `CdnNodeDoesNotExist` error if the CDN node does not exist. #[ink(message)] - pub fn cdn_node_get(&self, cdn_node_key: CdnNodeKey) -> Result { + pub fn cdn_node_get( + &self, + cdn_node_key: CdnNodeKey + ) -> Result { self.message_cdn_node_get(cdn_node_key) } - /// Iterate through all nodes. + /// Gets a paginated list of CDN nodes. /// + /// This enpoint gets a paginated list of CDN nodes along with their parameters. /// The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`. /// The optimal `limit` depends on the size of params. /// - /// The results can be filtered by owner. Note that paging must still be completed fully. + /// # Parameters + /// + /// * `offset` - starting offset. + /// * `limit` - page limit. + /// * `filter_provider_id` - optional filter by CDN node owner. + /// + /// # Errors + /// + /// No errors. In case a pagination param is out of bounds, an empty list will be returned. #[ink(message)] pub fn cdn_node_list( &self, offset: u32, limit: u32, filter_provider_id: Option, - ) -> (Vec, u32) { + ) -> (Vec, u32) { self.message_cdn_node_list(offset, limit, filter_provider_id) } - /// Remove cdn node by id - /// - /// Only the provider of the node can remove the node (not related to the public key) - /// - /// The underlying algorithm swaps the moved to be removed with the last one added, hence the id of the last one added will be updated - #[ink(message)] - pub fn cdn_node_remove(&mut self, node_key: CdnNodeKey) -> Result<()> { - self.message_remove_cdn_node(node_key) - } } // ---- End CDN Node ---- @@ -729,104 +1023,182 @@ pub mod ddc_bucket { } impl DdcBucket { - /// As node provider, authorize a cluster manager to use his nodes. - #[ink(message, payable)] - pub fn node_trust_manager(&mut self, manager: AccountId) { - self.message_node_trust_manager(manager, true).unwrap(); - } - - /// As node provider, revoke the authorization of a cluster manager to use his nodes. - #[ink(message)] - pub fn node_distrust_manager(&mut self, manager: AccountId) { - self.message_node_trust_manager(manager, false).unwrap(); - } - - /// Create a new node and return its `node_id`. + // /// As node provider, authorize a cluster manager to use his nodes. + // #[ink(message, payable)] + // pub fn node_trust_manager(&mut self, manager: AccountId) { + // self.message_node_trust_manager(manager, true).unwrap(); + // } + + // /// As node provider, revoke the authorization of a cluster manager to use his nodes. + // #[ink(message)] + // pub fn node_distrust_manager(&mut self, manager: AccountId) { + // self.message_node_trust_manager(manager, false).unwrap(); + // } + + /// Creates a Storage node + /// + /// This endpoint creates a Storage node with specific parameters. + /// The caller will be the node owner (node provider). + /// + /// # Parameters /// - /// The caller will be its owner. + /// * `node_key` - Public Keys of the Storage node that should be treated as node identifier. + /// * `node_params` - [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. + /// * `rent_per_month` - Amount to be paid for renting monthly. + /// * `capacity` - Measure used to evaluate physical node hardware resources. + /// * `status` - Status for the creating Storage node, can be one of the following: ACTIVE, ADDING, DELETING, OFFLINE. /// - /// `node_params` is configuration used by clients and nodes. In particular, this contains the URL to the service. See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema) + /// # Output + /// + /// Returns Public Key of the created Storage node. + /// + /// # Errors + /// + /// Returns `NodeAlreadyExists` error if a Storage node with the same Public Key is already created. + /// Returns `InvalidParams(message)` error if there is some invalid configuration parameter. #[ink(message, payable)] pub fn node_create( &mut self, node_key: NodeKey, - rent_per_month: Balance, node_params: NodeParams, + rent_per_month: Balance, capacity: Resource, - node_tag: NodeTag, + status: NodeStatus, ) -> NodeKey { - self.message_node_create(node_key, rent_per_month, node_params, capacity, node_tag) + self.message_node_create(node_key, rent_per_month, node_params, capacity, status) .unwrap() } - /// Change the `node_params`, which is configuration used by clients and nodes. + /// Removes a Storage node. /// - /// See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema) + /// This enpoint removes the targeting Storage Node if it is not added to some cluster. + /// Only a node that is not a member of some cluster can be removed. + /// + /// # Parameters + /// + /// * `node_key` - Public Key associated with the Storage node. + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// Returns `UnauthorizedNodeOwner` error if the caller is not the Storage node owner. + /// Returns `NodeDoesNotExist` error if the Storage node does not exist. + /// Returns `NodeIsAddedToCluster(cluster_id)` error if the removing Storage node is added to some cluster. + #[ink(message)] + pub fn node_remove( + &mut self, + node_key: NodeKey + ) { + self.message_remove_node(node_key).unwrap(); + } + + /// Changes parameters for the targeting Storage node. + /// + /// This enpoint updates [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. + /// All Storage node parameters must be specified as the endpoint works using SET approach. + /// + /// # Parameters + /// + /// * `node_key` - Public Key associated with the Storage node. + /// * `node_params` - [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// Returns `UnauthorizedNodeOwner` error if the caller is not the Storage node owner. + /// Returns `NodeDoesNotExist` error if the Storage node does not exist. #[ink(message, payable)] - pub fn node_change_params(&mut self, node_key: NodeKey, node_params: NodeParams) { + pub fn node_change_params( + &mut self, + node_key: NodeKey, + node_params: NodeParams + ) { self.message_node_change_params(node_key, node_params).unwrap(); } - /// Get the current status of a node. + /// Gets a Storage node. + /// + /// This enpoint gets the targeting Storage node along with its parameters. + /// + /// # Parameters + /// + /// * `node_key` - Public Key associated with the Storage node. + /// + /// # Output + /// + /// Returns `NodeInfo` data transfer object. + /// + /// # Errors + /// + /// Returns `NodeDoesNotExist` error if the Storage node does not exist. #[ink(message)] - pub fn node_get(&self, node_key: NodeKey) -> Result { + pub fn node_get( + &self, + node_key: NodeKey + ) -> Result { self.message_node_get(node_key) } - /// Iterate through all nodes. + /// Gets a paginated list of Storage nodes. /// + /// This enpoint gets a paginated list of Storage nodes along with their parameters. /// The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`. /// The optimal `limit` depends on the size of params. /// - /// The results can be filtered by owner. Note that paging must still be completed fully. + /// # Parameters + /// + /// * `offset` - starting offset. + /// * `limit` - page limit. + /// * `filter_provider_id` - optional filter by Storage node owner. + /// + /// # Errors + /// + /// No errors. In case a pagination param is out of bounds, an empty list will be returned. #[ink(message)] pub fn node_list( &self, offset: u32, limit: u32, filter_provider_id: Option, - ) -> (Vec, u32) { + ) -> (Vec, u32) { self.message_node_list(offset, limit, filter_provider_id) } - /// Remove node by id - /// - /// Only the provider of the node can remove the node (not related to the public key) - /// - /// The underlying algorithm swaps the moved to be removed with the last one added, hence the id of the last one added will be updated - #[ink(message)] - pub fn node_remove(&mut self, node_key: NodeKey) -> Result<()> { - self.message_remove_node(node_key) - } } // ---- End Node ---- // ---- Protocol ---- impl DdcBucket { - /// Get the Fee Percentage Basis Points that will be charged by the protocol - #[ink(message)] - pub fn get_fee_bp(&self) -> u32 { - self.message_get_fee_bp() - } - - /// Return the last commit submitted by CDN node operator - #[ink(message)] - pub fn set_fee_bp(&mut self, fee_bp: u32) -> () { - self.message_set_fee_bp(fee_bp).unwrap(); - } - - /// Return fees accumulated by the protocol - #[ink(message)] - pub fn get_protocol_revenues(&self) -> Cash { - self.message_get_fee_revenues() - } - - /// Pay the revenues accumulated by the protocol - #[ink(message)] - pub fn protocol_withdraw_revenues(&mut self, amount: u128) -> () { - self.message_withdraw_revenues(amount).unwrap(); - } + // /// Get the Fee Percentage Basis Points that will be charged by the protocol + // #[ink(message)] + // pub fn get_fee_bp(&self) -> u32 { + // self.message_get_fee_bp() + // } + + // /// Return the last commit submitted by CDN node operator + // #[ink(message)] + // pub fn set_fee_bp(&mut self, fee_bp: u32) -> () { + // self.message_set_fee_bp(fee_bp).unwrap(); + // } + + // /// Return fees accumulated by the protocol + // #[ink(message)] + // pub fn get_protocol_revenues(&self) -> Cash { + // self.message_get_fee_revenues() + // } + + // /// Pay the revenues accumulated by the protocol + // #[ink(message)] + // pub fn protocol_withdraw_revenues(&mut self, amount: u128) -> () { + // self.message_withdraw_revenues(amount).unwrap(); + // } } // ---- End Protocol ---- @@ -842,52 +1214,52 @@ pub mod ddc_bucket { } impl DdcBucket { - /// As user, deposit tokens on the account of the caller from the transaction value. This deposit - /// can be used to pay for the services to buckets of the account. - #[ink(message, payable)] - pub fn account_deposit(&mut self) -> () { - self.message_account_deposit().unwrap() - } - - /// As user, bond some amount of tokens from the withdrawable balance. These funds will be used to pay for CDN node service. - #[ink(message, payable)] - pub fn account_bond(&mut self, bond_amount: Balance) -> () { - self.message_account_bond(bond_amount).unwrap() - } - - /// As user, unbond a specified amount of tokens. The tokens will be locked for some time, as defined by contract owner. - #[ink(message, payable)] - pub fn account_unbond(&mut self, amount_to_unbond: Cash) -> () { - self.message_account_unbond(amount_to_unbond).unwrap() - } - - /// As user, move the unbonded tokens back to withdrawable balance state. - /// - /// This can be triggered after unbonded_timestamp - #[ink(message, payable)] - pub fn account_withdraw_unbonded(&mut self) -> () { - self.message_account_withdraw_unbonded().unwrap() - } - - /// Get the current status of an account. - #[ink(message)] - pub fn account_get(&self, account_id: AccountId) -> Result { - Ok(self.accounts.get(&account_id)?.clone()) - } - - /// Get the current conversion rate between the native currency and an external currency (USD). - #[ink(message)] - pub fn account_get_usd_per_cere(&self) -> Balance { - self.message_account_get_usd_per_cere() - } - - /// As price oracle, set the current conversion rate between the native currency and an external currency (USD). - /// - /// This requires the permission SetExchangeRate or SuperAdmin. - #[ink(message)] - pub fn account_set_usd_per_cere(&mut self, usd_per_cere: Balance) { - self.message_account_set_usd_per_cere(usd_per_cere); - } + // /// As user, deposit tokens on the account of the caller from the transaction value. This deposit + // /// can be used to pay for the services to buckets of the account. + // #[ink(message, payable)] + // pub fn account_deposit(&mut self) -> () { + // self.message_account_deposit().unwrap() + // } + + // /// As user, bond some amount of tokens from the withdrawable balance. These funds will be used to pay for CDN node service. + // #[ink(message, payable)] + // pub fn account_bond(&mut self, bond_amount: Balance) -> () { + // self.message_account_bond(bond_amount).unwrap() + // } + + // /// As user, unbond a specified amount of tokens. The tokens will be locked for some time, as defined by contract owner. + // #[ink(message, payable)] + // pub fn account_unbond(&mut self, amount_to_unbond: Cash) -> () { + // self.message_account_unbond(amount_to_unbond).unwrap() + // } + + // /// As user, move the unbonded tokens back to withdrawable balance state. + // /// + // /// This can be triggered after unbonded_timestamp + // #[ink(message, payable)] + // pub fn account_withdraw_unbonded(&mut self) -> () { + // self.message_account_withdraw_unbonded().unwrap() + // } + + // /// Get the current status of an account. + // #[ink(message)] + // pub fn account_get(&self, account_id: AccountId) -> Result { + // Ok(self.accounts.get(&account_id)?.clone()) + // } + + // /// Get the current conversion rate between the native currency and an external currency (USD). + // #[ink(message)] + // pub fn account_get_usd_per_cere(&self) -> Balance { + // self.message_account_get_usd_per_cere() + // } + + // /// As price oracle, set the current conversion rate between the native currency and an external currency (USD). + // /// + // /// This requires the permission SetExchangeRate or SuperAdmin. + // #[ink(message)] + // pub fn account_set_usd_per_cere(&mut self, usd_per_cere: Balance) { + // self.message_account_set_usd_per_cere(usd_per_cere); + // } } // ---- End Billing ---- @@ -914,51 +1286,200 @@ pub mod ddc_bucket { /// Check whether the given account has the given permission currently, /// or the SuperAdmin permission. #[ink(message)] - pub fn has_permission(&self, grantee: AccountId, permission: Permission) -> bool { + pub fn has_permission( + &self, grantee: AccountId, + permission: Permission + ) -> bool { self.perms.has_permission(grantee, permission) } + + /// Grants permissions for a cluster manager. + /// + /// This endpoint grants permissions for a cluster manager ro manage Storage or CDN node owner. + /// After the permission is granted, the cluster manager can add nodes to the cluster. + /// Permissions can be granted by Storage or CDN node owner. + /// + /// # Parameters + /// + /// * `cluster_manager` - cluster manager account. + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// No errors. The endpoint is idempotent. + #[ink(message, payable)] + pub fn trust_manager( + &mut self, + cluster_manager: AccountId + ) { + self.message_node_trust_manager(cluster_manager, true).unwrap(); + } + + /// Revokes permissions from cluster manager. + /// + /// This endpoint revokes permissions from a cluster manager to manage Storage or CDN node owner. + /// After the permission is revoked, the cluster manager can add nodes to the cluster. + /// Permissions can be revoked by Storage or CDN node owner. + /// + /// # Parameters + /// + /// * `cluster_manager` - cluster manager account. + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// No errors. The endpoint is idempotent. + #[ink(message)] + pub fn distrust_manager( + &mut self, + cluster_manager: AccountId + ) { + self.message_node_trust_manager(cluster_manager, false).unwrap(); + } + } // ---- End Permissions ---- // ---- Admin ---- impl DdcBucket { - /// As SuperAdmin, grant any permission to any account. - #[ink(message, payable)] - pub fn admin_grant_permission(&mut self, grantee: AccountId, permission: Permission) { + + /// Grants any permission. + /// + /// This endpoint grants any permissions for any account by the Super-admin. + /// + /// # Parameters + /// + /// * `grantee` - account to grant permission. + /// * `permission` - permission type. + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// Returns `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. + #[ink(message)] + pub fn admin_grant_permission( + &mut self, + grantee: AccountId, + permission: Permission + ) { self.message_admin_grant_permission(grantee, permission, true) .unwrap(); } - /// As SuperAdmin, revoke any permission to any account. + /// Revokes any permission. + /// + /// This endpoint revokes any permissions from any account by the Super-admin. + /// + /// # Parameters + /// + /// * `grantee` - account to revoke permission. + /// * `permission` - permission type. + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// Returns `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. #[ink(message)] - pub fn admin_revoke_permission(&mut self, grantee: AccountId, permission: Permission) { + pub fn admin_revoke_permission( + &mut self, + grantee: AccountId, + permission: Permission + ) { self.message_admin_grant_permission(grantee, permission, false) .unwrap(); } - /// As SuperAdmin, withdraw the funds held in custody in this contract. + /// Transfers Storage node ownership. + /// + /// This endpoint transfers Storage node ownership from Super-admin account to the targeting account forever. + /// This action is usually required only once after the Storage node certification process. + /// + /// # Parameters + /// + /// * `node_key` - Public Key associated with the Storage node. + /// * `owner` - Storage node owner /// - /// This is a temporary measure to allow migrating the funds to a new version of the contract. + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// Returns `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. + /// Returns `NodeDoesNotExist` error if the Storage node does not exist. + /// Returns `NodeOwnerIsNotSuperAdmin` error if the owner of the targeting node is not the Super-admin. #[ink(message)] - pub fn admin_withdraw(&mut self, amount: Balance) { - self.message_admin_withdraw(amount).unwrap(); + pub fn admin_transfer_node_ownership( + &mut self, + node_key: NodeKey, + owner: AccountId + ) { + } - /// As SuperAdmin, set the network and cluster fee configuration. + /// Transfers CDN node ownership. + /// + /// This endpoint transfers CDN node ownership from Super-admin account to the targeting account forever. + /// This action is usually required only once after the CDN node certification process. + /// + /// # Parameters + /// + /// * `cdn_node_key` - Public Key associated with the CDN node. + /// * `owner` - CDN node owner + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Errors + /// + /// Returns `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. + /// Returns `CdnNodeDoesNotExist` error if the Storage node does not exist. + /// Returns `CdnNodeOwnerIsNotSuperAdmin` error if the owner of the targeting node is not the Super-admin. #[ink(message)] - pub fn admin_set_fee_config(&mut self, config: FeeConfig) { - self.message_admin_set_fee_config(config).unwrap(); + pub fn admin_transfer_cdn_node_ownership( + &mut self, + node_key: CdnNodeKey, + owner: AccountId + ) { + } + + // /// As SuperAdmin, withdraw the funds held in custody in this contract. + // /// + // /// This is a temporary measure to allow migrating the funds to a new version of the contract. + // #[ink(message)] + // pub fn admin_withdraw(&mut self, amount: Balance) { + // self.message_admin_withdraw(amount).unwrap(); + // } + + // /// As SuperAdmin, set the network and cluster fee configuration. + // #[ink(message)] + // pub fn admin_set_fee_config(&mut self, config: FeeConfig) { + // self.message_admin_set_fee_config(config).unwrap(); + // } } // ---- End Admin ---- // ---- Accounts ---- impl DdcBucket { - /// Get all Account IDs stored in the SC - #[ink(message, payable)] - pub fn get_accounts(&self) -> Vec { - self.message_get_accounts() - } + // /// Get all Account IDs stored in the SC + // #[ink(message, payable)] + // pub fn get_accounts(&self) -> Vec { + // self.message_get_accounts() + // } } // ---- End Accounts ---- diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index 6ddb3046..08cae7f1 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -1265,7 +1265,7 @@ "label": "new_tag", "type": { "displayName": [ - "NodeTag" + "NodeStatus" ], "type": 27 } @@ -2149,7 +2149,7 @@ "label": "node_tag", "type": { "displayName": [ - "NodeTag" + "NodeStatus" ], "type": 27 } @@ -3661,7 +3661,7 @@ { "name": "node_tag", "type": 27, - "typeName": "NodeTag" + "typeName": "NodeStatus" }, { "name": "node_params", @@ -3714,7 +3714,7 @@ "ddc_bucket", "node", "entity", - "NodeTag" + "NodeStatus" ] } }, @@ -4411,7 +4411,7 @@ "ddc_bucket", "cluster", "entity", - "ClusterStatus" + "ClusterInfo" ] } }, @@ -4746,7 +4746,7 @@ "ddc_bucket", "cdn_node", "entity", - "CdnNodeStatus" + "CdnNodeInfo" ] } }, @@ -4879,7 +4879,7 @@ "ddc_bucket", "node", "entity", - "NodeStatus" + "NodeInfo" ] } }, From 1b89bf5be54c373dc880760f6c7a7b71d9ba3f52 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 15 Jun 2023 11:46:17 +0200 Subject: [PATCH 05/89] chore(prems) permission messages are split --- bucket/ddc_bucket/perm/messages.rs | 6 +- bucket/ddc_bucket/tests/env_utils.rs | 4 +- bucket/ddc_bucket/tests/test_admin.rs | 8 +- bucket/ddc_bucket/tests/test_contract.rs | 8 +- bucket/lib.rs | 335 ++++++++++++++++++----- scripts/sdk/src/abi/ddc_bucket.json | 4 +- 6 files changed, 289 insertions(+), 76 deletions(-) diff --git a/bucket/ddc_bucket/perm/messages.rs b/bucket/ddc_bucket/perm/messages.rs index 5d8e7324..9df47b04 100644 --- a/bucket/ddc_bucket/perm/messages.rs +++ b/bucket/ddc_bucket/perm/messages.rs @@ -2,7 +2,7 @@ use ink_lang::codegen::{EmitEvent, StaticEnv}; -use crate::ddc_bucket::{AccountId, DdcBucket, GrantPermission, Result, RevokePermission}; +use crate::ddc_bucket::{AccountId, DdcBucket, PermissionGranted, Result, PermissionRevoked}; use crate::ddc_bucket::Error::Unauthorized; use crate::ddc_bucket::perm::entity::Permission; @@ -10,11 +10,11 @@ impl DdcBucket { pub fn impl_grant_permission(&mut self, account_id: AccountId, permission: Permission, is_granted: bool) -> Result<()> { if is_granted { self.perms.grant_permission(account_id, &permission); - Self::env().emit_event(GrantPermission { account_id, permission }); + Self::env().emit_event(PermissionGranted { account_id, permission }); Ok(()) } else { self.perms.revoke_permission(account_id, &permission); - Self::env().emit_event(RevokePermission { account_id, permission }); + Self::env().emit_event(PermissionRevoked { account_id, permission }); Ok(()) } } diff --git a/bucket/ddc_bucket/tests/env_utils.rs b/bucket/ddc_bucket/tests/env_utils.rs index e84bca93..fd58af7c 100644 --- a/bucket/ddc_bucket/tests/env_utils.rs +++ b/bucket/ddc_bucket/tests/env_utils.rs @@ -76,8 +76,8 @@ pub fn print_events(events: &[Event]) { Event::BucketSettlePayment(ev) => println!("EVENT {:?}", ev), Event::BucketAvailabilityUpdated(ev) => println!("EVENT {:?}", ev), Event::Deposit(ev) => println!("EVENT {:?}", ev), - Event::GrantPermission(ev) => println!("EVENT {:?}", ev), - Event::RevokePermission(ev) => println!("EVENT {:?}", ev), + Event::PermissionGranted(ev) => println!("EVENT {:?}", ev), + Event::PermissionRevoked(ev) => println!("EVENT {:?}", ev), Event::CdnClusterCreated(ev) => println!("EVENT {:?}", ev), Event::CdnClusterDistributeRevenues(ev) => println!("EVENT {:?}", ev), Event::CdnNodeCreated(ev) => println!("EVENT {:?}", ev), diff --git a/bucket/ddc_bucket/tests/test_admin.rs b/bucket/ddc_bucket/tests/test_admin.rs index 8c4c22c0..4e4d6097 100644 --- a/bucket/ddc_bucket/tests/test_admin.rs +++ b/bucket/ddc_bucket/tests/test_admin.rs @@ -52,8 +52,8 @@ fn admin_grant_works() { // Check the last event. let ev = get_events().pop().unwrap(); - assert!(matches!(ev, Event::GrantPermission(ev) if ev == - GrantPermission { account_id: not_admin_id(), permission })); + assert!(matches!(ev, Event::PermissionGranted(ev) if ev == + PermissionGranted { account_id: not_admin_id(), permission })); assert!(contract.has_permission(new_admin_id, permission)); @@ -84,8 +84,8 @@ fn admin_revoke_works() { // Check the last event. let ev = get_events().pop().unwrap(); - assert!(matches!(ev, Event::RevokePermission(ev) if ev == - RevokePermission { account_id: not_admin_id(), permission })); + assert!(matches!(ev, Event::PermissionRevoked(ev) if ev == + PermissionRevoked { account_id: not_admin_id(), permission })); assert!(!contract.has_permission(admin_id(), permission)); diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index 86c0de68..5e7ad05d 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -386,8 +386,8 @@ fn cluster_create_works() { // Providers trust Manager. for provider_id in provider_ids { assert!( - matches!(evs.pop().unwrap(), Event::GrantPermission(ev) if ev == - GrantPermission { account_id: ctx.manager, permission: Permission::ManagerTrustedBy(*provider_id) }) + matches!(evs.pop().unwrap(), Event::PermissionGranted(ev) if ev == + PermissionGranted { account_id: ctx.manager, permission: Permission::ManagerTrustedBy(*provider_id) }) ); } @@ -821,8 +821,8 @@ fn cluster_add_node() { set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); ctx.contract.node_trust_manager(ctx.manager); assert!( - matches!(get_events().pop().unwrap(), Event::GrantPermission(ev) if ev == - GrantPermission { account_id: ctx.manager, permission: Permission::ManagerTrustedBy(new_provider_id) }) + matches!(get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == + PermissionGranted { account_id: ctx.manager, permission: Permission::ManagerTrustedBy(new_provider_id) }) ); let mut node_keys = Vec::::new(); diff --git a/bucket/lib.rs b/bucket/lib.rs index e8700f12..21e08553 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -314,7 +314,6 @@ pub mod ddc_bucket { // ---- Cluster ---- - /// A new cluster was created. #[ink(event)] #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] pub struct ClusterCreated { @@ -325,6 +324,74 @@ pub mod ddc_bucket { cluster_params: ClusterParams, } + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct ClusterNodeAdded { + #[ink(topic)] + cluster_id: ClusterId, + #[ink(topic)] + node_key: NodeKey, + } + + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct ClusterNodeRemoved { + #[ink(topic)] + cluster_id: ClusterId, + #[ink(topic)] + node_key: NodeKey, + } + + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct ClusterCdnNodeAdded { + #[ink(topic)] + cluster_id: ClusterId, + #[ink(topic)] + cdn_node_key: CdnNodeKey, + } + + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct ClusterCdnNodeRemoved { + #[ink(topic)] + cluster_id: ClusterId, + #[ink(topic)] + cdn_node_key: CdnNodeKey, + } + + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct ClusterParamsChanged { + #[ink(topic)] + cluster_id: ClusterId, + params: ClusterParams, + } + + + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct ClusterRemoved { + #[ink(topic)] + cluster_id: ClusterId, + } + + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct ClusterNodeStatusSet { + #[ink(topic)] + node_key: NodeKey, + status: NodeStatus + } + + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct ClusterCdnNodeStatusSet { + #[ink(topic)] + cdn_node_key: CdnNodeKey, + status: NodeStatus + } + /// A vnode was re-assigned to new node. #[ink(event)] #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] @@ -359,7 +426,7 @@ pub mod ddc_bucket { /// Creates a cluster of Storage nodes and CDN nodes. /// /// This endpoint creates a cluster of Storage nodes and CDN nodes with specific parameters. - /// The caller will be the cluster owner (cluster manager). In order to add a Storage or CDN node, the manager must be authorized by the node owner using the `trust_manager` endpoint. + /// The caller will be the cluster owner (cluster manager). In order to add a Storage or CDN node, the manager must be authorized by the node owner using the `trust_manager` endpoint or be the node owner. /// /// # Parameters /// @@ -372,14 +439,18 @@ pub mod ddc_bucket { /// /// Returns ID of the created cluster. /// + /// # Events + /// + /// * `ClusterCreated` event on successful cluster creation. + /// /// # Errors /// - /// Returns `ClusterManagerIsNotTrusted` error if the caller has a lack of trusted manager permissions for nodes he is trying to add. - /// Returns `NodeDoesNotExist` error if the adding Storage node does not exist. - /// Returns `InvalidVirtualNodes` error if there is a mismatch between adding Storage nodes and its virtual nodes. - /// Returns `CdnNodeDoesNotExist` error if the adding CDN node does not exist. - /// Returns `NodeIsAlreadyAddedToCluster(cluster_id)` error if an adding Storage node is already added to this or another cluster. - /// Returns `CdnNodeIsAlreadyAddedToCluster(cluster_id)` error if an adding CDN node is already added to this or another cluster. + /// * `ClusterManagerIsNotTrusted` error if the caller has a lack of trusted manager permissions for nodes he is trying to add. + /// * `NodeDoesNotExist` error if the adding Storage node does not exist. + /// * `InvalidVirtualNodes` error if there is a mismatch between adding Storage nodes and its virtual nodes. + /// * `CdnNodeDoesNotExist` error if the adding CDN node does not exist. + /// * `NodeIsAlreadyAddedToCluster(cluster_id)` error if an adding Storage node is already added to this or another cluster. + /// * `CdnNodeIsAlreadyAddedToCluster(cluster_id)` error if an adding CDN node is already added to this or another cluster. #[ink(message, payable)] pub fn cluster_create( &mut self, @@ -409,13 +480,17 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `ClusterNodeAdded` event on successful Storage node addition. + /// /// # Errors /// - /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. - /// Returns `ClusterDoesNotExist` error if the cluster does not exist. - /// Returns `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. - /// Returns `NodeDoesNotExist` error if the adding Storage node does not exist. - /// Returns `NodeIsAlreadyAddedToCluster(cluster_id)` error if the adding Storage node is already added to this or another cluster. + /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `ClusterDoesNotExist` error if the cluster does not exist. + /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// * `NodeDoesNotExist` error if the adding Storage node does not exist. + /// * `NodeIsAlreadyAddedToCluster(cluster_id)` error if the adding Storage node is already added to this or another cluster. #[ink(message, payable)] pub fn cluster_add_node( &mut self, @@ -441,13 +516,17 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `ClusterNodeRemoved` event on successful Storage node removal. + /// /// # Errors /// - /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. - /// Returns `ClusterDoesNotExist` error if the cluster does not exist. - /// Returns `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. - /// Returns `NodeDoesNotExist` error if the removing Storage node does not exist. - /// Returns `NodeIsNotInCluster(cluster_id)` error if the removing Storage node is not in this cluster. + /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `ClusterDoesNotExist` error if the cluster does not exist. + /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// * `NodeDoesNotExist` error if the removing Storage node does not exist. + /// * `NodeIsNotInCluster(cluster_id)` error if the removing Storage node is not in this cluster. #[ink(message)] pub fn cluster_remove_node( &mut self, @@ -472,13 +551,17 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `ClusterCdnNodeAdded` event on successful CDN node addition. + /// /// # Errors /// - /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. - /// Returns `ClusterDoesNotExist` error if the cluster does not exist. - /// Returns `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. - /// Returns `CdnNodeDoesNotExist` error if the adding CDN node does not exist. - /// Returns `CdnNodeIsAlreadyAddedToCluster(cluster_id)` error if the adding CDN node is already added to this or another cluster. + /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `ClusterDoesNotExist` error if the cluster does not exist. + /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// * `CdnNodeDoesNotExist` error if the adding CDN node does not exist. + /// * `CdnNodeIsAlreadyAddedToCluster(cluster_id)` error if the adding CDN node is already added to this or another cluster. #[ink(message, payable)] pub fn cluster_add_cdn_node( &mut self, @@ -502,13 +585,17 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `ClusterCdnNodeRemoved` event on successful CDN node removal. + /// /// # Errors /// - /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. - /// Returns `ClusterDoesNotExist` error if the cluster does not exist. - /// Returns `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. - /// Returns `CdnNodeDoesNotExist` error if the removing CDN node does not exist. - /// Returns `CdnNodeIsNotInCluster(cluster_id)` error if the removing CDN node is not in this cluster. + /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `ClusterDoesNotExist` error if the cluster does not exist. + /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// * `CdnNodeDoesNotExist` error if the removing CDN node does not exist. + /// * `CdnNodeIsNotInCluster(cluster_id)` error if the removing CDN node is not in this cluster. #[ink(message)] pub fn cluster_remove_cdn_node( &mut self, @@ -517,7 +604,7 @@ pub mod ddc_bucket { ) { } - + /// Changes parameters for the targeting cluster. /// /// This enpoint updates [cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. @@ -532,10 +619,14 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `ClusterParamsChanged` event on successful cluster params change.. + /// /// # Errors /// - /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. - /// Returns `ClusterDoesNotExist` error if the cluster does not exist. + /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `ClusterDoesNotExist` error if the cluster does not exist. #[ink(message, payable)] pub fn cluster_change_params( &mut self, @@ -559,11 +650,15 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `ClusterRemoved` event on successful cluster removal. + /// /// # Errors /// - /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. - /// Returns `ClusterDoesNotExist` error if the cluster does not exist. - /// Returns `ClusterIsNotEmpty` error if the removing cluster contains some Storage or CDN nodes. + /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `ClusterDoesNotExist` error if the cluster does not exist. + /// * `ClusterIsNotEmpty` error if the removing cluster contains some Storage or CDN nodes. #[ink(message)] pub fn cluster_remove( &mut self, @@ -585,10 +680,14 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `ClusterNodeStatusSet` event on successful Storage status change. + /// /// # Errors /// - /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. - /// Returns `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. #[ink(message)] pub fn cluster_set_node_status( &mut self, @@ -611,10 +710,14 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `ClusterCdnNodeStatusSet` event on successful CDN status change. + /// /// # Errors /// - /// Returns `UnauthorizedClusterOwner` error if the caller is not the cluster owner. - /// Returns `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. #[ink(message)] pub fn cluster_set_cdn_node_status( &mut self, @@ -637,7 +740,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// Returns `ClusterDoesNotExist` error if the cluster does not exist. + /// * `ClusterDoesNotExist` error if the cluster does not exist. #[ink(message)] pub fn cluster_get( &self, @@ -863,6 +966,21 @@ pub mod ddc_bucket { undistributed_payment: Balance, } + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct CdnNodeRemoved { + #[ink(topic)] + cdn_node_key: CdnNodeKey, + } + + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct CdnNodeParamsChanged { + #[ink(topic)] + cdn_node_key: CdnNodeKey, + cdn_node_params: CdnNodeParams, + } + impl DdcBucket { // /// As node provider, authorize a cluster manager to use his nodes. // #[ink(message, payable)] @@ -890,10 +1008,14 @@ pub mod ddc_bucket { /// /// Returns Public Key of the created CDN node. /// + /// # Events + /// + /// * `CdnNodeCreated` event on successful CDN node creation. + /// /// # Errors /// - /// Returns `CdnNodeAlreadyExists` error if a CDN node with the same Public Key is already created. - /// Returns `InvalidParams(message)` error if there is some invalid configuration parameter. + /// * `CdnNodeAlreadyExists` error if a CDN node with the same Public Key is already created. + /// * `InvalidParams(message)` error if there is some invalid configuration parameter. #[ink(message, payable)] pub fn cdn_node_create( &mut self, @@ -916,11 +1038,15 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `CdnNodeRemoved` event on successful CDN node removal. + /// /// # Errors /// - /// Returns `UnauthorizedCdnNodeOwner` error if the caller is not the CDN node owner. - /// Returns `CdnNodeDoesNotExist` error if the CDN node does not exist. - /// Returns `CdnNodeIsAddedToCluster(cluster_id)` error if the removing CDN node is added to some cluster. + /// * `UnauthorizedCdnNodeOwner` error if the caller is not the CDN node owner. + /// * `CdnNodeDoesNotExist` error if the CDN node does not exist. + /// * `CdnNodeIsAddedToCluster(cluster_id)` error if the removing CDN node is added to some cluster. #[ink(message)] pub fn cdn_node_remove( &mut self, @@ -943,10 +1069,14 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `CdnNodeParamsChanged` event on successful CDN node params change. + /// /// # Errors /// - /// Returns `UnauthorizedCdnNodeOwner` error if the caller is not the CDN node owner. - /// Returns `CdnNodeDoesNotExist` error if the CDN node does not exist. + /// * `UnauthorizedCdnNodeOwner` error if the caller is not the CDN node owner. + /// * `CdnNodeDoesNotExist` error if the CDN node does not exist. #[ink(message, payable)] pub fn cdn_node_change_params( &mut self, @@ -971,7 +1101,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// Returns `CdnNodeDoesNotExist` error if the CDN node does not exist. + /// * `CdnNodeDoesNotExist` error if the CDN node does not exist. #[ink(message)] pub fn cdn_node_get( &self, @@ -1022,6 +1152,21 @@ pub mod ddc_bucket { node_params: NodeParams, } + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct NodeRemoved { + #[ink(topic)] + node_key: NodeKey, + } + + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct NodeParamsChanged { + #[ink(topic)] + node_key: NodeKey, + node_params: NodeParams, + } + impl DdcBucket { // /// As node provider, authorize a cluster manager to use his nodes. // #[ink(message, payable)] @@ -1052,10 +1197,14 @@ pub mod ddc_bucket { /// /// Returns Public Key of the created Storage node. /// + /// # Events + /// + /// * `NodeCreated` event on successful Storage node creation. + /// /// # Errors /// - /// Returns `NodeAlreadyExists` error if a Storage node with the same Public Key is already created. - /// Returns `InvalidParams(message)` error if there is some invalid configuration parameter. + /// * `NodeAlreadyExists` error if a Storage node with the same Public Key is already created. + /// * `InvalidParams(message)` error if there is some invalid configuration parameter. #[ink(message, payable)] pub fn node_create( &mut self, @@ -1082,11 +1231,15 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `NodeRemoved` event on successful Storage node removal. + /// /// # Errors /// - /// Returns `UnauthorizedNodeOwner` error if the caller is not the Storage node owner. - /// Returns `NodeDoesNotExist` error if the Storage node does not exist. - /// Returns `NodeIsAddedToCluster(cluster_id)` error if the removing Storage node is added to some cluster. + /// * `UnauthorizedNodeOwner` error if the caller is not the Storage node owner. + /// * `NodeDoesNotExist` error if the Storage node does not exist. + /// * `NodeIsAddedToCluster(cluster_id)` error if the removing Storage node is added to some cluster. #[ink(message)] pub fn node_remove( &mut self, @@ -1109,10 +1262,14 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `NodeParamsChanged` event on successful Storage node params change. + /// /// # Errors /// - /// Returns `UnauthorizedNodeOwner` error if the caller is not the Storage node owner. - /// Returns `NodeDoesNotExist` error if the Storage node does not exist. + /// * `UnauthorizedNodeOwner` error if the caller is not the Storage node owner. + /// * `NodeDoesNotExist` error if the Storage node does not exist. #[ink(message, payable)] pub fn node_change_params( &mut self, @@ -1136,7 +1293,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// Returns `NodeDoesNotExist` error if the Storage node does not exist. + /// * `NodeDoesNotExist` error if the Storage node does not exist. #[ink(message)] pub fn node_get( &self, @@ -1267,7 +1424,7 @@ pub mod ddc_bucket { /// A permission was granted to the account. #[ink(event)] #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] - pub struct GrantPermission { + pub struct PermissionGranted { #[ink(topic)] account_id: AccountId, permission: Permission, @@ -1276,21 +1433,37 @@ pub mod ddc_bucket { /// A permission was revoked from the account. #[ink(event)] #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] - pub struct RevokePermission { + pub struct PermissionRevoked { #[ink(topic)] account_id: AccountId, permission: Permission, } impl DdcBucket { - /// Check whether the given account has the given permission currently, - /// or the SuperAdmin permission. + /// Checks for permission existence. + /// + /// This enpoint checks whether the given account has the given permission. + /// Super-admin will always have all permissions. + /// + /// # Parameters + /// + /// * `account_id` - account to check permissions. + /// * `permission` - permission to check. + /// + /// # Output + /// + /// Returns true if the account has permissions, false otherwise. + /// + /// # Errors + /// + /// No errors. #[ink(message)] pub fn has_permission( - &self, grantee: AccountId, + &self, + account_id: AccountId, permission: Permission ) -> bool { - self.perms.has_permission(grantee, permission) + self.perms.has_permission(account_id, permission) } /// Grants permissions for a cluster manager. @@ -1307,6 +1480,10 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `PermissionGranted` event on successful manager permissions granting + /// /// # Errors /// /// No errors. The endpoint is idempotent. @@ -1332,6 +1509,10 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `PermissionRevoked` event on successful manager permissions revoking + /// /// # Errors /// /// No errors. The endpoint is idempotent. @@ -1346,6 +1527,22 @@ pub mod ddc_bucket { } // ---- End Permissions ---- + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct NodeOwnershipTransferred { + #[ink(topic)] + account_id: AccountId, + node_key: NodeKey, + } + + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct CdnNodeOwnershipTransferred { + #[ink(topic)] + account_id: AccountId, + cdn_node_key: CdnNodeKey, + } + // ---- Admin ---- impl DdcBucket { @@ -1362,6 +1559,10 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `PermissionGranted` event on successful permissions granting + /// /// # Errors /// /// Returns `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. @@ -1388,6 +1589,10 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `PermissionRevoked` event on successful permissions revoking + /// /// # Errors /// /// Returns `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. @@ -1415,6 +1620,10 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `NodeOwnershipTransferred` event on successful Storage node ownership transfer + /// /// # Errors /// /// Returns `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. @@ -1443,6 +1652,10 @@ pub mod ddc_bucket { /// /// Returns nothing. /// + /// # Events + /// + /// * `CdnNodeOwnershipTransferred` event on successful CDN node ownership transfer + /// /// # Errors /// /// Returns `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index 08cae7f1..8718ca90 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -514,7 +514,7 @@ "docs": [ " A permission was granted to the account." ], - "label": "GrantPermission" + "label": "PermissionGranted" }, { "args": [ @@ -544,7 +544,7 @@ "docs": [ " A permission was revoked from the account." ], - "label": "RevokePermission" + "label": "PermissionRevoked" } ], "messages": [ From 9dfdc373f2f44c6b1939c24cf8e1de8506993eb9 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 15 Jun 2023 13:46:49 +0200 Subject: [PATCH 06/89] chore(cdn): setting cdn node params --- bucket/lib.rs | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/bucket/lib.rs b/bucket/lib.rs index 21e08553..e225ef1c 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -362,7 +362,7 @@ pub mod ddc_bucket { #[ink(event)] #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] - pub struct ClusterParamsChanged { + pub struct ClusterParamsSet { #[ink(topic)] cluster_id: ClusterId, params: ClusterParams, @@ -605,7 +605,7 @@ pub mod ddc_bucket { } - /// Changes parameters for the targeting cluster. + /// Sets parameters for the targeting cluster. /// /// This enpoint updates [cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. /// All cluster parameters must be specified as the endpoint works using SET approach. @@ -621,14 +621,14 @@ pub mod ddc_bucket { /// /// # Events /// - /// * `ClusterParamsChanged` event on successful cluster params change.. + /// * `ClusterParamsSet` event on successful cluster params setting. /// /// # Errors /// /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. #[ink(message, payable)] - pub fn cluster_change_params( + pub fn cluster_set_params( &mut self, cluster_id: ClusterId, cluster_params: ClusterParams @@ -975,7 +975,7 @@ pub mod ddc_bucket { #[ink(event)] #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] - pub struct CdnNodeParamsChanged { + pub struct CdnNodeParamsSet { #[ink(topic)] cdn_node_key: CdnNodeKey, cdn_node_params: CdnNodeParams, @@ -1055,7 +1055,7 @@ pub mod ddc_bucket { self.message_remove_cdn_node(cdn_node_key).unwrap(); } - /// Changes parameters for the targeting CDN node. + /// Sets parameters for the targeting CDN node. /// /// This enpoint updates [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. /// All CDN node parameters must be specified as the endpoint works using SET approach. @@ -1071,14 +1071,14 @@ pub mod ddc_bucket { /// /// # Events /// - /// * `CdnNodeParamsChanged` event on successful CDN node params change. + /// * `CdnNodeParamsSet` event on successful CDN node params setting. /// /// # Errors /// /// * `UnauthorizedCdnNodeOwner` error if the caller is not the CDN node owner. /// * `CdnNodeDoesNotExist` error if the CDN node does not exist. #[ink(message, payable)] - pub fn cdn_node_change_params( + pub fn cdn_node_set_params( &mut self, cdn_node_key: CdnNodeKey, cdn_node_params: CdnNodeParams @@ -1161,7 +1161,7 @@ pub mod ddc_bucket { #[ink(event)] #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] - pub struct NodeParamsChanged { + pub struct NodeParamsSet { #[ink(topic)] node_key: NodeKey, node_params: NodeParams, @@ -1248,7 +1248,7 @@ pub mod ddc_bucket { self.message_remove_node(node_key).unwrap(); } - /// Changes parameters for the targeting Storage node. + /// Sets parameters for the targeting Storage node. /// /// This enpoint updates [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. /// All Storage node parameters must be specified as the endpoint works using SET approach. @@ -1264,14 +1264,14 @@ pub mod ddc_bucket { /// /// # Events /// - /// * `NodeParamsChanged` event on successful Storage node params change. + /// * `NodeParamsSet` event on successful Storage node params setting. /// /// # Errors /// /// * `UnauthorizedNodeOwner` error if the caller is not the Storage node owner. /// * `NodeDoesNotExist` error if the Storage node does not exist. #[ink(message, payable)] - pub fn node_change_params( + pub fn node_set_params( &mut self, node_key: NodeKey, node_params: NodeParams @@ -1488,7 +1488,7 @@ pub mod ddc_bucket { /// /// No errors. The endpoint is idempotent. #[ink(message, payable)] - pub fn trust_manager( + pub fn grant_manager_permission( &mut self, cluster_manager: AccountId ) { @@ -1517,7 +1517,7 @@ pub mod ddc_bucket { /// /// No errors. The endpoint is idempotent. #[ink(message)] - pub fn distrust_manager( + pub fn revoke_manager_permission( &mut self, cluster_manager: AccountId ) { @@ -1626,9 +1626,9 @@ pub mod ddc_bucket { /// /// # Errors /// - /// Returns `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. - /// Returns `NodeDoesNotExist` error if the Storage node does not exist. - /// Returns `NodeOwnerIsNotSuperAdmin` error if the owner of the targeting node is not the Super-admin. + /// * `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. + /// * `NodeDoesNotExist` error if the Storage node does not exist. + /// * `NodeOwnerIsNotSuperAdmin` error if the owner of the targeting node is not the Super-admin. #[ink(message)] pub fn admin_transfer_node_ownership( &mut self, @@ -1658,9 +1658,9 @@ pub mod ddc_bucket { /// /// # Errors /// - /// Returns `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. - /// Returns `CdnNodeDoesNotExist` error if the Storage node does not exist. - /// Returns `CdnNodeOwnerIsNotSuperAdmin` error if the owner of the targeting node is not the Super-admin. + /// * `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. + /// * `CdnNodeDoesNotExist` error if the Storage node does not exist. + /// * `CdnNodeOwnerIsNotSuperAdmin` error if the owner of the targeting node is not the Super-admin. #[ink(message)] pub fn admin_transfer_cdn_node_ownership( &mut self, From d230d9e62718610c187735c2a4bcf2aa4c7a4663 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 15 Jun 2023 14:31:04 +0200 Subject: [PATCH 07/89] chore(node): setting node status --- bucket/lib.rs | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/bucket/lib.rs b/bucket/lib.rs index e225ef1c..7fcec6c0 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -526,7 +526,7 @@ pub mod ddc_bucket { /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. /// * `NodeDoesNotExist` error if the removing Storage node does not exist. - /// * `NodeIsNotInCluster(cluster_id)` error if the removing Storage node is not in this cluster. + /// * `NodeIsNotInCluster` error if the removing Storage node is not in this cluster. #[ink(message)] pub fn cluster_remove_node( &mut self, @@ -595,7 +595,7 @@ pub mod ddc_bucket { /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. /// * `CdnNodeDoesNotExist` error if the removing CDN node does not exist. - /// * `CdnNodeIsNotInCluster(cluster_id)` error if the removing CDN node is not in this cluster. + /// * `CdnNodeIsNotInCluster` error if the removing CDN node is not in this cluster. #[ink(message)] pub fn cluster_remove_cdn_node( &mut self, @@ -673,6 +673,7 @@ pub mod ddc_bucket { /// /// # Parameters /// + /// * `cluster_id` - ID of the targeting cluster. /// * `node_key` - Public Key associated with the Storage node. /// * `status` - Status for the targeting Storage node, can be one of the following: ACTIVE, ADDING, DELETING, OFFLINE. /// @@ -687,10 +688,13 @@ pub mod ddc_bucket { /// # Errors /// /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// * `NodeIsNotInCluster` error if the Storage node is not in this cluster. #[ink(message)] pub fn cluster_set_node_status( &mut self, + cluster_id: ClusterId, node_key: NodeKey, status: NodeStatus ) { @@ -703,6 +707,7 @@ pub mod ddc_bucket { /// /// # Parameters /// + /// * `cluster_id` - ID of the targeting cluster. /// * `cdn_node_key` - Public Key associated with the CDN node. /// * `status` - Status for the targeting CDN node, can be one of the following: ACTIVE, ADDING, DELETING, OFFLINE. /// @@ -717,10 +722,13 @@ pub mod ddc_bucket { /// # Errors /// /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// * `CdnNodeIsNotInCluster` error if the Storage node is not in this cluster. #[ink(message)] pub fn cluster_set_cdn_node_status( &mut self, + cluster_id: ClusterId, cdn_node_key: NodeKey, status: NodeStatus ) { @@ -1189,9 +1197,7 @@ pub mod ddc_bucket { /// /// * `node_key` - Public Keys of the Storage node that should be treated as node identifier. /// * `node_params` - [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. - /// * `rent_per_month` - Amount to be paid for renting monthly. /// * `capacity` - Measure used to evaluate physical node hardware resources. - /// * `status` - Status for the creating Storage node, can be one of the following: ACTIVE, ADDING, DELETING, OFFLINE. /// /// # Output /// @@ -1210,11 +1216,9 @@ pub mod ddc_bucket { &mut self, node_key: NodeKey, node_params: NodeParams, - rent_per_month: Balance, capacity: Resource, - status: NodeStatus, ) -> NodeKey { - self.message_node_create(node_key, rent_per_month, node_params, capacity, status) + self.message_node_create(node_key, Balance::default(), node_params, capacity, NodeStatus::ACTIVE) .unwrap() } From 45d1f2e5968e7a9f7fab5415b4d4aa229f5b2698 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 15 Jun 2023 14:32:43 +0200 Subject: [PATCH 08/89] chore(cdn): cdn node key type --- bucket/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bucket/lib.rs b/bucket/lib.rs index 7fcec6c0..1fb742bc 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -729,7 +729,7 @@ pub mod ddc_bucket { pub fn cluster_set_cdn_node_status( &mut self, cluster_id: ClusterId, - cdn_node_key: NodeKey, + cdn_node_key: CdnNodeKey, status: NodeStatus ) { } From cebd3f55a7e3e3b9397be71b31d572f4c821dda1 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Tue, 20 Jun 2023 23:59:19 +0200 Subject: [PATCH 09/89] chore(documentation): documentation comments --- bucket/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bucket/lib.rs b/bucket/lib.rs index 1fb742bc..99b2a210 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -1668,7 +1668,7 @@ pub mod ddc_bucket { #[ink(message)] pub fn admin_transfer_cdn_node_ownership( &mut self, - node_key: CdnNodeKey, + cdn_node_key: CdnNodeKey, owner: AccountId ) { From 9e92d77091d590de867b62999a38b997fa9127b4 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 21 Jun 2023 01:44:53 +0200 Subject: [PATCH 10/89] feat(node): basic api for storage node --- .gitignore | 1 + bucket/ddc_bucket/cdn_node/entity.rs | 8 +- bucket/ddc_bucket/node/entity.rs | 29 ++++--- bucket/ddc_bucket/node/messages.rs | 98 +++++++++++++++--------- bucket/ddc_bucket/node/store.rs | 12 +-- bucket/ddc_bucket/tests/test_contract.rs | 16 ++-- bucket/lib.rs | 41 +++++----- scripts/sdk/src/abi/ddc_bucket.json | 4 +- 8 files changed, 124 insertions(+), 85 deletions(-) diff --git a/.gitignore b/.gitignore index 23409363..2f4d2bfb 100755 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ Cargo.lock local .idea ink-doc-gen +.DS_Store diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index f2cd6d56..a2810f9a 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -39,8 +39,12 @@ impl CdnNode { self.provider_id } - pub fn only_owner(&self, provider_id: AccountId) -> Result<()> { - if self.provider_id == provider_id { Ok(()) } else { Err(UnauthorizedProvider) } + pub fn only_owner(&self, owner_id: AccountId) -> Result<()> { + if self.provider_id == owner_id { + Ok(()) + } else { + Err(UnauthorizedCdnNodeOwner) + } } pub fn put_payment(&mut self, amount: Balance) { diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index 3690be0a..8a3ddc01 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -5,6 +5,8 @@ use scale::{Decode, Encode}; use crate::ddc_bucket::params::store::Params; use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; +use crate::ddc_bucket::cluster::entity::ClusterId; + use ink_storage::traits::KeyPtr; use ink_primitives::Key; @@ -19,8 +21,9 @@ pub struct Node { pub provider_id: ProviderId, pub rent_per_month: Balance, pub free_resource: Resource, - pub node_tag: NodeStatus, - pub node_params: NodeParams + pub node_params: NodeParams, + pub status: NodeStatus, + pub cluster_id: Option } // https://use.ink/3.x/ink-vs-solidity#nested-mappings--custom--advanced-structures @@ -34,7 +37,7 @@ impl ink_storage::traits::PackedAllocate for Node { #[derive(Clone, PartialEq, Encode, Decode, SpreadLayout, PackedLayout)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] pub enum NodeStatus { - UNKNOWN, + CREATED, ACTIVE, ADDING, DELETING, @@ -43,13 +46,13 @@ pub enum NodeStatus { impl SpreadAllocate for NodeStatus { fn allocate_spread(_: &mut KeyPtr) -> Self { - NodeStatus::UNKNOWN + NodeStatus::CREATED } } impl Default for NodeStatus { fn default() -> Self { - NodeStatus::UNKNOWN + NodeStatus::CREATED } } @@ -65,16 +68,16 @@ impl Node { self.provider_id } - pub fn only_owner(&self, provider_id: AccountId) -> Result<()> { - if self.provider_id == provider_id { + pub fn only_owner(&self, owner_id: AccountId) -> Result<()> { + if self.provider_id == owner_id { Ok(()) } else { - Err(UnauthorizedProvider) + Err(UnauthorizedNodeOwner) } } pub fn change_tag(&mut self, new_tag: NodeStatus) { - self.node_tag = new_tag; + self.status = new_tag; } pub fn put_resource(&mut self, amount: Resource) { @@ -89,4 +92,12 @@ impl Node { Err(InsufficientResources) } } + + pub fn only_without_cluster(&self) -> Result<()> { + if let Some(cluster_id) = self.cluster_id { + Err(NodeIsAddedToCluster(cluster_id)) + } else { + Ok(()) + } + } } diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index 9076e6b3..648ceb0a 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -2,40 +2,34 @@ use crate::ddc_bucket::node::entity::{NodeInfo, Resource, NodeKey, NodeParams, NodeStatus}; use crate::ddc_bucket::perm::entity::Permission; -use crate::ddc_bucket::{AccountId, Balance, DdcBucket, NodeCreated, Result}; +use crate::ddc_bucket::{AccountId, Balance, DdcBucket, NodeCreated, NodeRemoved, NodeParamsSet, Result}; use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; impl DdcBucket { - pub fn message_node_trust_manager( - &mut self, - manager: AccountId, - is_trusted: bool, - ) -> Result<()> { - let trust_giver = Self::env().caller(); - let permission = Permission::ManagerTrustedBy(trust_giver); - self.impl_grant_permission(manager, permission, is_trusted) - } pub fn message_node_create( &mut self, node_key: NodeKey, - rent_per_month: Balance, node_params: NodeParams, capacity: Resource, - node_tag: NodeStatus, + rent_per_month: Balance, ) -> Result { - let provider_id = Self::env().caller(); - let node_key = self - .nodes - .create(node_key, provider_id, rent_per_month, node_params.clone(), capacity, node_tag) - .unwrap(); + let caller = Self::env().caller(); + self.nodes + .create( + node_key, + caller, + node_params.clone(), + capacity, + rent_per_month + )?; Self::env().emit_event(NodeCreated { node_key, - provider_id, + provider_id: caller, rent_per_month, node_params, }); @@ -43,35 +37,48 @@ impl DdcBucket { Ok(node_key) } - pub fn message_node_change_tag(&mut self, node_key: NodeKey, new_tag: NodeStatus) -> Result<()> { + pub fn message_remove_node( + &mut self, + node_key: NodeKey + ) -> Result<()> { + let caller = Self::env().caller(); - let mut node = self.nodes.get(node_key)?; + let node = self.nodes.get(node_key)?; node.only_owner(caller)?; - node.change_tag(new_tag); - self.nodes.update(node_key, &node)?; - Ok(()) - } + node.only_without_cluster()?; + self.nodes.remove(node_key) - pub fn message_node_get(&self, node_key: NodeKey) -> Result { - let node = self.nodes.get(node_key)?; - Ok(NodeInfo { - node_key, - node, - }) } - pub fn message_node_change_params( + pub fn message_node_set_params( &mut self, node_key: NodeKey, node_params: NodeParams, ) -> Result<()> { - + let caller = Self::env().caller(); let mut node = self.nodes.get(node_key)?; node.only_owner(caller)?; - node.node_params = node_params; + node.node_params = node_params.clone(); self.nodes.update(node_key, &node)?; + + Self::env().emit_event(NodeParamsSet { + node_key, + node_params, + }); + Ok(()) + + } + + pub fn message_node_get(&self, node_key: NodeKey) -> Result { + + let node = self.nodes.get(node_key)?; + Ok(NodeInfo { + node_key, + node, + }) + } pub fn message_node_list( @@ -80,6 +87,7 @@ impl DdcBucket { limit: u32, filter_provider_id: Option, ) -> (Vec, u32) { + let mut nodes = Vec::with_capacity(limit as usize); for idx in offset..offset + limit { let node_key = match self.nodes.keys.get(idx as usize) { @@ -106,13 +114,31 @@ impl DdcBucket { } (nodes, self.nodes.keys.len().try_into().unwrap()) + } - pub fn message_remove_node(&mut self, node_key: NodeKey) -> Result<()> { + pub fn message_node_change_tag(&mut self, node_key: NodeKey, new_tag: NodeStatus) -> Result<()> { let caller = Self::env().caller(); - let node = self.nodes.get(node_key)?; + let mut node = self.nodes.get(node_key)?; node.only_owner(caller)?; - self.nodes.remove(node_key) + node.change_tag(new_tag); + self.nodes.update(node_key, &node)?; + + Self::env().emit_event(NodeRemoved { + node_key, + }); + + Ok(()) + } + + pub fn message_node_trust_manager( + &mut self, + manager: AccountId, + is_trusted: bool, + ) -> Result<()> { + let trust_giver = Self::env().caller(); + let permission = Permission::ManagerTrustedBy(trust_giver); + self.impl_grant_permission(manager, permission, is_trusted) } } \ No newline at end of file diff --git a/bucket/ddc_bucket/node/store.rs b/bucket/ddc_bucket/node/store.rs index 95641f12..e3b7dab1 100644 --- a/bucket/ddc_bucket/node/store.rs +++ b/bucket/ddc_bucket/node/store.rs @@ -13,7 +13,7 @@ use super::entity::{Node, NodeStatus, NodeKey, NodeParams, Resource}; #[cfg_attr(feature = "std", derive(StorageLayout, Debug))] pub struct NodeStore { pub nodes: Mapping, - // This vector is temporal and must be replaced with an offchain indexer + // This pagination vector is temporal and must be replaced with an offchain indexer pub keys: Vec } @@ -22,18 +22,18 @@ impl NodeStore { &mut self, node_key: AccountId, provider_id: AccountId, - rent_per_month: Balance, node_params: NodeParams, capacity: Resource, - node_tag: NodeStatus, + rent_per_month: Balance, ) -> Result { let node = Node { provider_id, - rent_per_month, + node_params, free_resource: capacity, - node_tag, - node_params + rent_per_month, + status: NodeStatus::CREATED, + cluster_id: None }; if self.nodes.contains(&node_key) { diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index 5e7ad05d..39f93d3f 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -321,7 +321,7 @@ fn cluster_create_works() { provider_id: ctx.provider_id0, rent_per_month: ctx.rent_per_vnode, free_resource: ctx.capacity - ctx.reserved * 3, - node_tag: NodeStatus::ADDING, + status: NodeStatus::ADDING, node_params: ctx.node_params0.to_string(), } } @@ -336,7 +336,7 @@ fn cluster_create_works() { provider_id: ctx.provider_id1, rent_per_month: ctx.rent_per_vnode, free_resource: ctx.capacity - ctx.reserved * 3, - node_tag: NodeStatus::ADDING, + status: NodeStatus::ADDING, node_params: ctx.node_params1.to_string(), } } @@ -351,7 +351,7 @@ fn cluster_create_works() { provider_id: ctx.provider_id2, rent_per_month: ctx.rent_per_vnode, free_resource: ctx.capacity - ctx.reserved * 3, - node_tag: NodeStatus::ADDING, + status: NodeStatus::ADDING, node_params: ctx.node_params2.to_string(), } } @@ -807,7 +807,7 @@ fn cluster_add_node() { let rent_per_month = 100; let node_params = "new_node"; let capacity = 1000; - let node_tag = NodeStatus::ACTIVE; + let status = NodeStatus::ACTIVE; set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); let new_node_id = ctx.contract.node_create( @@ -815,7 +815,7 @@ fn cluster_add_node() { rent_per_month, node_params.to_string(), capacity, - node_tag, + status, ); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); @@ -994,7 +994,7 @@ fn bucket_reserve_0_works() { provider_id: AccountId::default(), rent_per_month: 0, free_resource: 0, - node_tag: NodeStatus::ACTIVE, + status: NodeStatus::ACTIVE, node_params: "".to_string(), } }], @@ -1340,7 +1340,7 @@ fn node_list_works() { provider_id: owner_id1, rent_per_month, free_resource: capacity, - node_tag: NodeStatus::ADDING, + status: NodeStatus::ADDING, node_params: node_params1.to_string(), }, }; @@ -1351,7 +1351,7 @@ fn node_list_works() { provider_id: owner_id2, rent_per_month, free_resource: capacity, - node_tag: NodeStatus::ADDING, + status: NodeStatus::ADDING, node_params: node_params2.to_string(), }, }; diff --git a/bucket/lib.rs b/bucket/lib.rs index 99b2a210..51783a6d 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -96,15 +96,15 @@ pub mod ddc_bucket { // Reserve IDs 0. let _ = contract.accounts.create_if_not_exist(AccountId::default()); let _ = contract.cdn_nodes.create(AccountId::default(), AccountId::default(), "".to_string(), 0); + let _ = contract .nodes .create( AccountId::default(), AccountId::default(), + NodeParams::from(""), 0, - "".to_string(), - 0, - NodeStatus::ACTIVE, + Balance::default(), ) .unwrap(); let _ = contract @@ -1176,17 +1176,6 @@ pub mod ddc_bucket { } impl DdcBucket { - // /// As node provider, authorize a cluster manager to use his nodes. - // #[ink(message, payable)] - // pub fn node_trust_manager(&mut self, manager: AccountId) { - // self.message_node_trust_manager(manager, true).unwrap(); - // } - - // /// As node provider, revoke the authorization of a cluster manager to use his nodes. - // #[ink(message)] - // pub fn node_distrust_manager(&mut self, manager: AccountId) { - // self.message_node_trust_manager(manager, false).unwrap(); - // } /// Creates a Storage node /// @@ -1217,9 +1206,15 @@ pub mod ddc_bucket { node_key: NodeKey, node_params: NodeParams, capacity: Resource, - ) -> NodeKey { - self.message_node_create(node_key, Balance::default(), node_params, capacity, NodeStatus::ACTIVE) - .unwrap() + ) -> Result { + // todo: confirm do we need the 'rent_per_month' param + let rent_per_month = Balance::default(); + self.message_node_create( + node_key, + node_params, + capacity, + rent_per_month + ) } /// Removes a Storage node. @@ -1248,8 +1243,8 @@ pub mod ddc_bucket { pub fn node_remove( &mut self, node_key: NodeKey - ) { - self.message_remove_node(node_key).unwrap(); + ) -> Result<()> { + self.message_remove_node(node_key) } /// Sets parameters for the targeting Storage node. @@ -1279,8 +1274,8 @@ pub mod ddc_bucket { &mut self, node_key: NodeKey, node_params: NodeParams - ) { - self.message_node_change_params(node_key, node_params).unwrap(); + ) -> Result<()> { + self.message_node_set_params(node_key, node_params) } /// Gets a Storage node. @@ -1722,7 +1717,6 @@ pub mod ddc_bucket { FlowDoesNotExist, AccountDoesNotExist, ParamsDoesNotExist, - UnauthorizedProvider, UnauthorizedOwner, UnauthorizedClusterManager, ClusterManagerIsNotTrusted, @@ -1731,6 +1725,9 @@ pub mod ddc_bucket { InsufficientResources, Unauthorized, UnknownNode, + NodeIsAddedToCluster(ClusterId), + UnauthorizedNodeOwner, + UnauthorizedCdnNodeOwner } pub type Result = core::result::Result; diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index 8718ca90..595bfce2 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -2146,7 +2146,7 @@ } }, { - "label": "node_tag", + "label": "status", "type": { "displayName": [ "NodeStatus" @@ -3659,7 +3659,7 @@ "typeName": "Resource" }, { - "name": "node_tag", + "name": "status", "type": 27, "typeName": "NodeStatus" }, From 90d7b21794f0a1088870e52c521e1d0efec69a67 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 21 Jun 2023 02:16:02 +0200 Subject: [PATCH 11/89] feat(cdn-node): basic api for cdn node --- bucket/ddc_bucket/cdn_node/entity.rs | 13 ++++- bucket/ddc_bucket/cdn_node/messages.rs | 80 +++++++++++++++++++------- bucket/ddc_bucket/cdn_node/store.rs | 9 +-- bucket/ddc_bucket/node/messages.rs | 13 +++-- bucket/ddc_bucket/node/store.rs | 3 +- bucket/lib.rs | 25 +++----- 6 files changed, 90 insertions(+), 53 deletions(-) diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index a2810f9a..7c275a01 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -3,7 +3,7 @@ use ink_storage::traits::{SpreadAllocate, PackedLayout, SpreadLayout, PackedAllocate}; use scale::{Decode, Encode}; use ink_primitives::Key; -use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; +use crate::ddc_bucket::{AccountId, Balance, ClusterId, NodeStatus, Error::*, Result}; use crate::ddc_bucket::params::store::Params; pub type ProviderId = AccountId; @@ -17,6 +17,8 @@ pub struct CdnNode { pub provider_id: ProviderId, pub undistributed_payment: Balance, pub cdn_node_params: CdnNodeParams, + pub status: NodeStatus, + pub cluster_id: Option } // https://use.ink/3.x/ink-vs-solidity#nested-mappings--custom--advanced-structures @@ -59,4 +61,13 @@ impl CdnNode { Err(InsufficientBalance) } } + + pub fn only_without_cluster(&self) -> Result<()> { + if let Some(cluster_id) = self.cluster_id { + Err(CdnNodeIsAddedToCluster(cluster_id)) + } else { + Ok(()) + } + } + } \ No newline at end of file diff --git a/bucket/ddc_bucket/cdn_node/messages.rs b/bucket/ddc_bucket/cdn_node/messages.rs index b151eefc..263c367a 100644 --- a/bucket/ddc_bucket/cdn_node/messages.rs +++ b/bucket/ddc_bucket/cdn_node/messages.rs @@ -2,58 +2,93 @@ use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; -use crate::ddc_bucket::{AccountId, DdcBucket, CdnNodeCreated, Result, Balance}; +use crate::ddc_bucket::{AccountId, DdcBucket, CdnNodeCreated, CdnNodeRemoved, CdnNodeParamsSet, Result, Balance}; use crate::ddc_bucket::perm::entity::{Permission}; use super::entity::{CdnNodeKey, CdnNodeInfo, CdnNodeParams}; impl DdcBucket { - pub fn message_cdn_node_trust_manager(&mut self, manager: AccountId, is_trusted: bool) -> Result<()> { - let trust_giver = Self::env().caller(); - let permission = Permission::ManagerTrustedBy(trust_giver); - self.impl_grant_permission(manager, permission, is_trusted) - } - pub fn message_cdn_node_create(&mut self, cdn_node_key: CdnNodeKey, cdn_node_params: CdnNodeParams) -> Result { - let provider_id = Self::env().caller(); + pub fn message_cdn_node_create( + &mut self, + cdn_node_key: CdnNodeKey, + cdn_node_params: CdnNodeParams + ) -> Result { + let caller = Self::env().caller(); let undistributed_payment: Balance = 0; - - let cdn_node_key = self - .cdn_nodes - .create(cdn_node_key, provider_id, cdn_node_params.clone(), undistributed_payment) - .unwrap(); + self.cdn_nodes + .create( + cdn_node_key, + caller, + cdn_node_params.clone(), + undistributed_payment + )?; Self::env().emit_event(CdnNodeCreated { cdn_node_key, - provider_id, + provider_id: caller, cdn_node_params, undistributed_payment, }); Ok(cdn_node_key) + } - pub fn message_cdn_node_change_params(&mut self, cdn_node_key: CdnNodeKey, cdn_node_params: CdnNodeParams) -> Result<()> { + pub fn message_remove_cdn_node( + &mut self, + cdn_node_key: CdnNodeKey + ) -> Result<()> { + let caller = Self::env().caller(); + let cdn_node = self.cdn_nodes.get(cdn_node_key)?; + cdn_node.only_owner(caller)?; + cdn_node.only_without_cluster()?; + self.cdn_nodes.remove(cdn_node_key); + + Self::env().emit_event(CdnNodeRemoved { + cdn_node_key, + }); + + + Ok(()) + + } + pub fn message_cdn_node_set_params( + &mut self, + cdn_node_key: CdnNodeKey, + cdn_node_params: CdnNodeParams + ) -> Result<()> { + + let caller = Self::env().caller(); let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; cdn_node.only_owner(caller)?; - cdn_node.cdn_node_params = cdn_node_params; + cdn_node.cdn_node_params = cdn_node_params.clone(); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; + Self::env().emit_event(CdnNodeParamsSet { + cdn_node_key, + cdn_node_params, + }); + Ok(()) + } pub fn message_cdn_node_get(&self, cdn_node_key: CdnNodeKey) -> Result { + let cdn_node = self.cdn_nodes.get(cdn_node_key)?; Ok(CdnNodeInfo { cdn_node_key, cdn_node, }) + } pub fn message_cdn_node_list(&self, offset: u32, limit: u32, filter_provider_id: Option) -> (Vec, u32) { + let mut cdn_nodes = Vec::with_capacity(limit as usize); for idx in offset..offset + limit { let cdn_node_key = match self.cdn_nodes.keys.get(idx as usize) { @@ -62,7 +97,6 @@ impl DdcBucket { }; let cdn_node = self.cdn_nodes.cdn_nodes.get(cdn_node_key).unwrap(); - // Apply the filter if given. if let Some(provider_id) = filter_provider_id { if provider_id != cdn_node.provider_id { @@ -80,12 +114,14 @@ impl DdcBucket { } (cdn_nodes, self.cdn_nodes.keys.len().try_into().unwrap()) + } - pub fn message_remove_cdn_node(&mut self, cdn_node_key: CdnNodeKey) -> Result<()> { - let caller = Self::env().caller(); - let cdn_node = self.cdn_nodes.get(cdn_node_key)?; - cdn_node.only_owner(caller)?; - self.cdn_nodes.remove(cdn_node_key) + + pub fn message_cdn_node_trust_manager(&mut self, manager: AccountId, is_trusted: bool) -> Result<()> { + let trust_giver = Self::env().caller(); + let permission = Permission::ManagerTrustedBy(trust_giver); + self.impl_grant_permission(manager, permission, is_trusted) } + } diff --git a/bucket/ddc_bucket/cdn_node/store.rs b/bucket/ddc_bucket/cdn_node/store.rs index 392231b0..8415c8f8 100644 --- a/bucket/ddc_bucket/cdn_node/store.rs +++ b/bucket/ddc_bucket/cdn_node/store.rs @@ -4,7 +4,7 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; use ink_storage::Mapping; use ink_prelude::vec::Vec; -use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; +use crate::ddc_bucket::{AccountId, Balance, NodeStatus, Error::*, Result}; use super::entity::{CdnNode, CdnNodeKey, CdnNodeParams}; @@ -28,7 +28,9 @@ impl CdnNodeStore { let cdn_node = CdnNode { provider_id, cdn_node_params, - undistributed_payment + undistributed_payment, + status: NodeStatus::CREATED, + cluster_id: None }; if self.cdn_nodes.contains(&cdn_node_key) { @@ -54,12 +56,11 @@ impl CdnNodeStore { } } - pub fn remove(&mut self, cdn_node_key: CdnNodeKey) -> Result<()> { + pub fn remove(&mut self, cdn_node_key: CdnNodeKey) { self.cdn_nodes.remove(cdn_node_key); if let Some(pos) = self.keys.iter().position(|x| *x == cdn_node_key) { self.keys.remove(pos); }; - Ok(()) } } diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index 648ceb0a..493e5796 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -46,8 +46,14 @@ impl DdcBucket { let node = self.nodes.get(node_key)?; node.only_owner(caller)?; node.only_without_cluster()?; - self.nodes.remove(node_key) + self.nodes.remove(node_key); + Self::env().emit_event(NodeRemoved { + node_key, + }); + + Ok(()) + } pub fn message_node_set_params( @@ -96,7 +102,6 @@ impl DdcBucket { }; let node = self.nodes.nodes.get(node_key).unwrap(); - // Apply the filter if given. if let Some(provider_id) = filter_provider_id { if provider_id != node.provider_id { @@ -123,10 +128,6 @@ impl DdcBucket { node.only_owner(caller)?; node.change_tag(new_tag); self.nodes.update(node_key, &node)?; - - Self::env().emit_event(NodeRemoved { - node_key, - }); Ok(()) } diff --git a/bucket/ddc_bucket/node/store.rs b/bucket/ddc_bucket/node/store.rs index e3b7dab1..38e2f399 100644 --- a/bucket/ddc_bucket/node/store.rs +++ b/bucket/ddc_bucket/node/store.rs @@ -58,11 +58,10 @@ impl NodeStore { } } - pub fn remove(&mut self, node_key: NodeKey) -> Result<()> { + pub fn remove(&mut self, node_key: NodeKey) { self.nodes.remove(node_key); if let Some(pos) = self.keys.iter().position(|x| *x == node_key) { self.keys.remove(pos); }; - Ok(()) } } diff --git a/bucket/lib.rs b/bucket/lib.rs index 51783a6d..51224078 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -990,17 +990,6 @@ pub mod ddc_bucket { } impl DdcBucket { - // /// As node provider, authorize a cluster manager to use his nodes. - // #[ink(message, payable)] - // pub fn cdn_node_trust_manager(&mut self, manager: AccountId) { - // self.message_cdn_node_trust_manager(manager, true).unwrap(); - // } - - // /// As node provider, revoke the authorization of a cluster manager to use his nodes. - // #[ink(message)] - // pub fn cdn_node_distrust_manager(&mut self, manager: AccountId) { - // self.message_cdn_node_trust_manager(manager, false).unwrap(); - // } /// Creates a CDN node /// @@ -1029,8 +1018,8 @@ pub mod ddc_bucket { &mut self, cdn_node_key: CdnNodeKey, cdn_node_params: CdnNodeParams - ) -> CdnNodeKey { - self.message_cdn_node_create(cdn_node_key, cdn_node_params).unwrap() + ) -> Result { + self.message_cdn_node_create(cdn_node_key, cdn_node_params) } /// Removes a CDN node. @@ -1059,8 +1048,8 @@ pub mod ddc_bucket { pub fn cdn_node_remove( &mut self, cdn_node_key: CdnNodeKey - ) { - self.message_remove_cdn_node(cdn_node_key).unwrap(); + ) -> Result<()> { + self.message_remove_cdn_node(cdn_node_key) } /// Sets parameters for the targeting CDN node. @@ -1090,9 +1079,8 @@ pub mod ddc_bucket { &mut self, cdn_node_key: CdnNodeKey, cdn_node_params: CdnNodeParams - ) { - self.message_cdn_node_change_params(cdn_node_key, cdn_node_params) - .unwrap(); + ) -> Result<()> { + self.message_cdn_node_set_params(cdn_node_key, cdn_node_params) } /// Gets a CDN node. @@ -1726,6 +1714,7 @@ pub mod ddc_bucket { Unauthorized, UnknownNode, NodeIsAddedToCluster(ClusterId), + CdnNodeIsAddedToCluster(ClusterId), UnauthorizedNodeOwner, UnauthorizedCdnNodeOwner } From 198e856e0e63fdbd28c0992354c448132769fceb Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 22 Jun 2023 01:00:05 +0200 Subject: [PATCH 12/89] feat(cluster): common cluster for Storage and CDN nodes --- bucket/ddc_bucket/bucket/messages.rs | 36 ++++++----- bucket/ddc_bucket/cdn_cluster/messages.rs | 2 +- bucket/ddc_bucket/cdn_node/entity.rs | 16 +++++ bucket/ddc_bucket/cdn_node/store.rs | 46 +++++++------ bucket/ddc_bucket/cluster/entity.rs | 39 +++++++++--- bucket/ddc_bucket/cluster/messages.rs | 78 +++++++++++++++-------- bucket/ddc_bucket/cluster/store.rs | 52 ++++++++++----- bucket/ddc_bucket/node/entity.rs | 18 ++++++ bucket/ddc_bucket/node/store.rs | 17 +++-- bucket/lib.rs | 26 ++++---- 10 files changed, 217 insertions(+), 113 deletions(-) diff --git a/bucket/ddc_bucket/bucket/messages.rs b/bucket/ddc_bucket/bucket/messages.rs index 1a256b29..55a47a77 100644 --- a/bucket/ddc_bucket/bucket/messages.rs +++ b/bucket/ddc_bucket/bucket/messages.rs @@ -30,10 +30,11 @@ impl DdcBucket { pub fn message_bucket_alloc_into_cluster(&mut self, bucket_id: BucketId, resource: Resource) -> Result<()> { let bucket = self.buckets.get_mut(bucket_id)?; - let cluster = self.clusters.get_mut(bucket.cluster_id)?; - Self::only_owner_or_cluster_manager(bucket, cluster)?; + let mut cluster = self.clusters.get(bucket.cluster_id)?; + Self::only_owner_or_cluster_manager(bucket, &cluster)?; cluster.take_resource(resource)?; + self.clusters.update(bucket.cluster_id, &cluster)?; bucket.put_resource(resource); // Start the payment flow to the cluster. @@ -52,13 +53,15 @@ impl DdcBucket { let now_ms = Self::env().block_timestamp(); let cash = self.accounts.settle_flow(now_ms, &mut bucket.flow)?; - let cluster = self.clusters.get_mut(bucket.cluster_id)?; + let mut cluster = self.clusters.get(bucket.cluster_id)?; cluster.revenues.increase(cash); + self.clusters.update(bucket.cluster_id, &cluster)?; Self::env().emit_event(BucketSettlePayment { bucket_id, cluster_id: bucket.cluster_id }); Ok(()) } + pub fn message_bucket_change_params(&mut self, bucket_id: BucketId, params: BucketParams) -> Result<()> { let caller = Self::env().caller(); let bucket = self.buckets.get(bucket_id)?; @@ -114,19 +117,20 @@ impl DdcBucket { pub fn message_bucket_set_resource_cap(&mut self, bucket_id: BucketId, new_resource_cap: Resource) -> Result<()> { let bucket = self.buckets.get_mut(bucket_id)?; - let cluster = self.clusters.get_mut(bucket.cluster_id)?; + let cluster = self.clusters.get(bucket.cluster_id)?; - Self::only_owner_or_cluster_manager(bucket, cluster)?; + Self::only_owner_or_cluster_manager(bucket, &cluster)?; bucket.set_cap(new_resource_cap); Ok(()) } pub fn message_bucket_set_availability(&mut self, bucket_id: BucketId, public_availability: bool) -> Result<()> { let bucket = self.buckets.get_mut(bucket_id)?; - let cluster = self.clusters.get_mut(bucket.cluster_id)?; - - Self::only_owner_or_cluster_manager(bucket, cluster)?; + let cluster = self.clusters.get(bucket.cluster_id)?; + + Self::only_owner_or_cluster_manager(bucket, &cluster)?; bucket.set_availability(public_availability); + Self::env().emit_event(BucketAvailabilityUpdated { bucket_id, public_availability }); Ok(()) } @@ -138,18 +142,18 @@ impl DdcBucket { pub fn message_grant_writer_permission(&mut self, bucket_id: BucketId, writer: AccountId) -> Result<()> { let bucket = self.buckets.get_mut(bucket_id)?; - let cluster = self.clusters.get_mut(bucket.cluster_id)?; + let cluster = self.clusters.get(bucket.cluster_id)?; - Self::only_owner_or_cluster_manager(bucket, cluster)?; + Self::only_owner_or_cluster_manager(bucket, &cluster)?; self.buckets_perms.grant_writer_permission(bucket_id, writer).unwrap(); Ok(()) } pub fn message_revoke_writer_permission(&mut self, bucket_id: BucketId, writer: AccountId) -> Result<()> { let bucket = self.buckets.get_mut(bucket_id)?; - let cluster = self.clusters.get_mut(bucket.cluster_id)?; + let cluster = self.clusters.get(bucket.cluster_id)?; - Self::only_owner_or_cluster_manager(bucket, cluster)?; + Self::only_owner_or_cluster_manager(bucket, &cluster)?; self.buckets_perms.revoke_writer_permission(bucket_id, writer).unwrap(); Ok(()) } @@ -161,18 +165,18 @@ impl DdcBucket { pub fn message_grant_reader_permission(&mut self, bucket_id: BucketId, reader: AccountId) -> Result<()> { let bucket = self.buckets.get_mut(bucket_id)?; - let cluster = self.clusters.get_mut(bucket.cluster_id)?; + let cluster = self.clusters.get(bucket.cluster_id)?; - Self::only_owner_or_cluster_manager(bucket, cluster)?; + Self::only_owner_or_cluster_manager(bucket, &cluster)?; self.buckets_perms.grant_reader_permission(bucket_id, reader).unwrap(); Ok(()) } pub fn message_revoke_reader_permission(&mut self, bucket_id: BucketId, reader: AccountId) -> Result<()> { let bucket = self.buckets.get_mut(bucket_id)?; - let cluster = self.clusters.get_mut(bucket.cluster_id)?; + let cluster = self.clusters.get(bucket.cluster_id)?; - Self::only_owner_or_cluster_manager(bucket, cluster)?; + Self::only_owner_or_cluster_manager(bucket, &cluster)?; self.buckets_perms.revoke_reader_permission(bucket_id, reader).unwrap(); Ok(()) } diff --git a/bucket/ddc_bucket/cdn_cluster/messages.rs b/bucket/ddc_bucket/cdn_cluster/messages.rs index eadba173..90ded167 100644 --- a/bucket/ddc_bucket/cdn_cluster/messages.rs +++ b/bucket/ddc_bucket/cdn_cluster/messages.rs @@ -189,7 +189,7 @@ impl DdcBucket { }; clusters.push(status); } - (clusters, self.clusters.0.len().try_into().unwrap()) + (clusters, self.cdn_clusters.0.len().try_into().unwrap()) } fn only_cdn_cluster_manager(cluster: &CdnCluster) -> Result { diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index 7c275a01..8884f306 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -37,6 +37,22 @@ pub struct CdnNodeInfo { } impl CdnNode { + + pub fn new( + cdn_node_key: CdnNodeKey, + provider_id: AccountId, + cdn_node_params: CdnNodeParams, + undistributed_payment: Balance + ) -> Self { + CdnNode { + provider_id, + cdn_node_params, + undistributed_payment, + status: NodeStatus::CREATED, + cluster_id: None + } + } + pub fn cdn_account_id(&self) -> AccountId { self.provider_id } diff --git a/bucket/ddc_bucket/cdn_node/store.rs b/bucket/ddc_bucket/cdn_node/store.rs index 8415c8f8..1ff2e114 100644 --- a/bucket/ddc_bucket/cdn_node/store.rs +++ b/bucket/ddc_bucket/cdn_node/store.rs @@ -17,31 +17,29 @@ pub struct CdnNodeStore { } impl CdnNodeStore { - pub fn create( - &mut self, - cdn_node_key: CdnNodeKey, - provider_id: AccountId, - cdn_node_params: CdnNodeParams, - undistributed_payment: Balance, - ) -> Result { + pub fn create( + &mut self, + cdn_node_key: CdnNodeKey, + provider_id: AccountId, + cdn_node_params: CdnNodeParams, + undistributed_payment: Balance, + ) -> Result { - let cdn_node = CdnNode { - provider_id, - cdn_node_params, - undistributed_payment, - status: NodeStatus::CREATED, - cluster_id: None - }; - - if self.cdn_nodes.contains(&cdn_node_key) { - Err(CdnNodeAlreadyExists) - } else { - self.cdn_nodes.insert(&cdn_node_key, &cdn_node); - self.keys.push(cdn_node_key); - Ok(cdn_node_key) - } - - } + if self.cdn_nodes.contains(&cdn_node_key) { + Err(CdnNodeAlreadyExists) + } else { + let cdn_node = CdnNode::new( + cdn_node_key, + provider_id, + cdn_node_params, + undistributed_payment + ); + self.cdn_nodes.insert(&cdn_node_key, &cdn_node); + self.keys.push(cdn_node_key); + Ok(cdn_node_key) + } + + } pub fn get(&self, cdn_node_key: CdnNodeKey) -> Result { self.cdn_nodes.get(cdn_node_key).ok_or(CdnNodeDoesNotExist) diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 112dd2ba..a2330310 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -7,6 +7,8 @@ use scale::{Decode, Encode}; use ink_primitives::Key; use crate::ddc_bucket::cash::Cash; use crate::ddc_bucket::node::entity::{Resource, NodeKey}; +use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; + use crate::ddc_bucket::params::store::Params; use crate::ddc_bucket::Error::UnauthorizedClusterManager; use crate::ddc_bucket::{AccountId, Balance, Error::InsufficientResources, Result}; @@ -20,12 +22,20 @@ pub type VNodeId = (ClusterId, VNodeIndex); #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] pub struct Cluster { pub manager_id: AccountId, + + pub nodes_keys: Vec, + pub v_nodes: Vec>, pub resource_per_vnode: Resource, pub resource_used: Resource, pub revenues: Cash, - pub node_keys: Vec, - pub v_nodes: Vec>, pub total_rent: Balance, + + pub cluster_params: ClusterParams, + + pub cdn_nodes_keys: Vec, + pub cdn_resources_used: Resource, + pub cdn_revenues: Cash, + pub cdn_usd_per_gb: Balance, } // https://use.ink/3.x/ink-vs-solidity#nested-mappings--custom--advanced-structures @@ -41,19 +51,30 @@ impl ink_storage::traits::PackedAllocate for Cluster { pub struct ClusterInfo { pub cluster_id: ClusterId, pub cluster: Cluster, - pub params: Params, } impl Cluster { - pub fn new(manager_id: AccountId, v_nodes_arr: &Vec>, node_keys: &Vec) -> Self { + + pub fn new( + manager_id: AccountId, + nodes_keys: Vec, + v_nodes: Vec>, + cdn_nodes_keys: Vec, + cluster_params: ClusterParams, + ) -> Self { Cluster { manager_id, + nodes_keys, + v_nodes, resource_per_vnode: 0, resource_used: 0, revenues: Cash(0), - v_nodes: v_nodes_arr.clone(), - node_keys: node_keys.clone(), total_rent: 0, + cluster_params, + cdn_nodes_keys, + cdn_usd_per_gb: 104_857_600, // setting initially to 1 cent per GB + cdn_resources_used: 0, + cdn_revenues: Cash(0), } } @@ -77,7 +98,7 @@ impl Cluster { // v_nodes should be sorted pub fn replace_v_node(&mut self, v_nodes: Vec, node_id: NodeKey) { let old_v_nodes = &self.v_nodes; - let old_node_keys = &self.node_keys; + let old_node_keys = &self.nodes_keys; let mut new_v_nodes = Vec::>::new(); let mut new_node_keys = Vec::::new(); @@ -123,7 +144,7 @@ impl Cluster { new_node_keys.push(node_id); self.v_nodes = new_v_nodes; - self.node_keys = new_node_keys; + self.nodes_keys = new_node_keys; } pub fn only_manager(&self, caller: AccountId) -> Result<()> { @@ -134,7 +155,7 @@ impl Cluster { } } - pub fn change_rent(&mut self, rent: Balance) { + pub fn set_rent(&mut self, rent: Balance) { self.total_rent = rent; } } diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 6292c5f8..a487bf71 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -5,7 +5,7 @@ use ink_prelude::vec::Vec; use crate::ddc_bucket::cash::{Cash, Payable}; use crate::ddc_bucket::cluster::entity::{Cluster, ClusterInfo}; use crate::ddc_bucket::node::entity::{Node, NodeKey, Resource}; -use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; +use crate::ddc_bucket::cdn_node::entity::{CdnNode, CdnNodeKey}; use crate::ddc_bucket::perm::entity::Permission; use crate::ddc_bucket::perm::store::PermStore; use crate::ddc_bucket::ClusterNodeReplaced; @@ -27,29 +27,48 @@ impl DdcBucket { ) -> Result { let manager = Self::env().caller(); - let mut nodes = Vec::<(NodeKey, Node)>::new(); + let mut nodes: Vec<(ink_env::AccountId, Node)> = Vec::<(NodeKey, Node)>::new(); for node_key in &nodes_keys { let node = self.nodes.get(*node_key)?; - // Verify that the node provider trusts the cluster manager. + node.only_without_cluster()?; Self::only_trusted_manager(&self.perms, manager, node.provider_id.clone())?; nodes.push((*node_key, node)); } - let cluster_id = self.clusters.create(manager, &v_nodes, &nodes_keys)?; + let mut cdn_nodes = Vec::<(CdnNodeKey, CdnNode)>::new(); + for cdn_node_key in &cdn_nodes_keys { + let cdn_node = self.cdn_nodes.get(*cdn_node_key)?; + cdn_node.only_without_cluster()?; + Self::only_trusted_manager(&self.perms, manager, cdn_node.provider_id.clone())?; + cdn_nodes.push((*cdn_node_key, cdn_node)); + } + + let cluster_id = self.clusters.create( + manager, + nodes_keys, + v_nodes.clone(), + cdn_nodes_keys, + cluster_params.clone() + )?; + let rent = self .topology_store - .create_topology(cluster_id, v_nodes, nodes.into_iter().map(|(key, node)| (key, node)).collect())?; + .create_topology( + cluster_id, + v_nodes, + nodes.into_iter().map(|(key, node)| (key, node)).collect() + )?; - self.clusters.get_mut(cluster_id).unwrap().change_rent(rent); - - let params_id = self.cluster_params.create(cluster_params.clone())?; - assert_eq!(cluster_id, params_id); + let mut cluster = self.clusters.get(cluster_id)?; + cluster.set_rent(rent); + self.clusters.update(cluster_id, &cluster)?; Self::env().emit_event(ClusterCreated { cluster_id, manager, cluster_params, }); + Ok(cluster_id) } @@ -84,10 +103,11 @@ impl DdcBucket { .topology_store .add_node(cluster_id, &old_v_nodes, &v_nodes, nodes.into_iter().map(|(key, node)| (key, node)).collect())?; - let cluster = self.clusters.get_mut(cluster_id)?; + let mut cluster = self.clusters.get(cluster_id)?; cluster.total_rent = total_rent as Balance; cluster.v_nodes = v_nodes; - cluster.node_keys = node_keys; + cluster.nodes_keys = node_keys; + self.clusters.update(cluster_id, &cluster)?; Ok(()) } @@ -97,9 +117,10 @@ impl DdcBucket { cluster_id: ClusterId, resource: Resource, ) -> Result<()> { - let cluster = self.clusters.get_mut(cluster_id)?; - Self::only_cluster_manager(cluster)?; + let mut cluster = self.clusters.get(cluster_id)?; + Self::only_cluster_manager(&cluster)?; cluster.put_resource(resource); + self.clusters.update(cluster_id, &cluster)?; for v_nodes_wrapper in &cluster.v_nodes { for &v_node in v_nodes_wrapper { @@ -124,8 +145,8 @@ impl DdcBucket { v_nodes: Vec, new_node_key: NodeKey, ) -> Result<()> { - let cluster = self.clusters.get_mut(cluster_id)?; - let manager = Self::only_cluster_manager(cluster)?; + let mut cluster = self.clusters.get(cluster_id)?; + let manager = Self::only_cluster_manager(&cluster)?; // Give back resources to the old node for all its v_nodes for v_node in v_nodes.clone() { @@ -153,6 +174,8 @@ impl DdcBucket { cluster.replace_v_node(v_nodes, new_node_key); + self.clusters.update(cluster_id, &cluster)?; + Self::env().emit_event(ClusterNodeReplaced { cluster_id, node_key: new_node_key, @@ -161,7 +184,7 @@ impl DdcBucket { } pub fn message_cluster_distribute_revenues(&mut self, cluster_id: ClusterId) -> Result<()> { - let cluster = self.clusters.get_mut(cluster_id)?; + let mut cluster = self.clusters.get(cluster_id)?; // Charge the network fee from the cluster. Self::capture_network_fee(&self.network_fee, &mut cluster.revenues)?; @@ -178,7 +201,7 @@ impl DdcBucket { let per_share = cluster.revenues.peek() / num_shares; cluster.revenues.pay(Payable(per_share * num_shares))?; - for node_key in &cluster.node_keys { + for node_key in &cluster.nodes_keys { let node = self.nodes.get(*node_key)?; Self::send_cash(node.provider_id, Cash(per_share))?; @@ -187,31 +210,33 @@ impl DdcBucket { provider_id: node.provider_id, }); } + + self.clusters.update(cluster_id, &cluster)?; + // TODO: set a maximum node count, or support paging. // TODO: aggregate the payments per node_id or per provider_id. Ok(()) } - pub fn message_cluster_change_params( + pub fn message_cluster_set_params( &mut self, cluster_id: ClusterId, - params: ClusterParams, + cluster_params: ClusterParams, ) -> Result<()> { let caller = Self::env().caller(); - let cluster = self.clusters.get(cluster_id)?; + let mut cluster: Cluster = self.clusters.get(cluster_id)?; cluster.only_manager(caller)?; - - Self::impl_change_params(&mut self.cluster_params, cluster_id, params) + cluster.cluster_params = cluster_params; + self.clusters.update(cluster_id, &cluster)?; + Ok(()) } pub fn message_cluster_get(&self, cluster_id: ClusterId) -> Result { let cluster = self.clusters.get(cluster_id)?.clone(); - let params = self.cluster_params.get(cluster_id)?.clone(); Ok(ClusterInfo { cluster_id, cluster, - params, }) } @@ -223,7 +248,7 @@ impl DdcBucket { ) -> (Vec, u32) { let mut clusters = Vec::with_capacity(limit as usize); for cluster_id in offset..offset + limit { - let cluster = match self.clusters.0.get(cluster_id as usize) { + let cluster = match self.clusters.clusters.get(cluster_id) { None => break, // No more items, stop. Some(cluster) => cluster, }; @@ -237,11 +262,10 @@ impl DdcBucket { let status = ClusterInfo { cluster_id, cluster: cluster.clone(), - params: self.cluster_params.get(cluster_id).unwrap().clone(), }; clusters.push(status); } - (clusters, self.clusters.0.len().try_into().unwrap()) + (clusters, self.clusters.next_cluster_id - 1) } fn only_cluster_manager(cluster: &Cluster) -> Result { diff --git a/bucket/ddc_bucket/cluster/store.rs b/bucket/ddc_bucket/cluster/store.rs index 2c1da452..ca8498be 100644 --- a/bucket/ddc_bucket/cluster/store.rs +++ b/bucket/ddc_bucket/cluster/store.rs @@ -2,38 +2,60 @@ use ink_prelude::vec::Vec; use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; +use ink_storage::Mapping; use crate::ddc_bucket::node::entity::{NodeKey}; +use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; use crate::ddc_bucket::{AccountId, Error::*, Result}; -use super::entity::{Cluster, ClusterId}; +use super::entity::{Cluster, ClusterId, ClusterParams}; #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(StorageLayout, Debug))] -pub struct ClusterStore(pub Vec); +pub struct ClusterStore { + pub clusters: Mapping, + pub next_cluster_id: u32 +} impl ClusterStore { pub fn create( &mut self, manager_id: AccountId, - v_nodes: &Vec>, - node_keys: &Vec, + nodes_keys: Vec, + v_nodes: Vec>, + cdn_nodes_keys: Vec, + cluster_params: ClusterParams, ) -> Result { - let cluster = Cluster::new(manager_id, v_nodes, node_keys); - - let cluster_id: ClusterId = self.0.len().try_into().unwrap(); - self.0.push(cluster); - + let cluster_id = self.next_cluster_id; + self.next_cluster_id = self.next_cluster_id + 1; + + let cluster = Cluster::new( + manager_id, + nodes_keys, + v_nodes, + cdn_nodes_keys, + cluster_params + ); + + self.clusters.insert(&cluster_id, &cluster); Ok(cluster_id) } - pub fn get(&self, cluster_id: ClusterId) -> Result<&Cluster> { - self.0.get(cluster_id as usize).ok_or(ClusterDoesNotExist) + pub fn get(&self, cluster_id: ClusterId) -> Result { + self.clusters.get(cluster_id).ok_or(ClusterDoesNotExist) } - pub fn get_mut(&mut self, cluster_id: ClusterId) -> Result<&mut Cluster> { - self.0 - .get_mut(cluster_id as usize) - .ok_or(ClusterDoesNotExist) + pub fn update(&mut self, cluster_id: ClusterId, cluster: &Cluster) -> Result<()> { + if !self.clusters.contains(&cluster_id) { + Err(ClusterDoesNotExist) + } else { + self.clusters.insert(cluster_id, cluster); + Ok(()) + } } + + pub fn remove(&mut self, cluster_id: ClusterId) { + self.clusters.remove(cluster_id); + } + } diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index 8a3ddc01..53a372a6 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -64,6 +64,24 @@ pub struct NodeInfo { } impl Node { + + pub fn new( + node_key: AccountId, + provider_id: AccountId, + node_params: NodeParams, + capacity: Resource, + rent_per_month: Balance, + ) -> Self { + Node { + provider_id, + node_params, + free_resource: capacity, + rent_per_month, + status: NodeStatus::CREATED, + cluster_id: None + } + } + pub fn revenue_account_id(&self) -> AccountId { self.provider_id } diff --git a/bucket/ddc_bucket/node/store.rs b/bucket/ddc_bucket/node/store.rs index 38e2f399..6f6ed3b7 100644 --- a/bucket/ddc_bucket/node/store.rs +++ b/bucket/ddc_bucket/node/store.rs @@ -26,23 +26,22 @@ impl NodeStore { capacity: Resource, rent_per_month: Balance, ) -> Result { - - let node = Node { - provider_id, - node_params, - free_resource: capacity, - rent_per_month, - status: NodeStatus::CREATED, - cluster_id: None - }; if self.nodes.contains(&node_key) { Err(NodeAlreadyExists) } else { + let node = Node::new( + node_key, + provider_id, + node_params, + capacity, + rent_per_month + ); self.nodes.insert(node_key, &node); self.keys.push(node_key); Ok(node_key) } + } pub fn get(&self, node_key: NodeKey) -> Result { diff --git a/bucket/lib.rs b/bucket/lib.rs index 51224078..fd60bc2a 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -64,7 +64,6 @@ pub mod ddc_bucket { bucket_params: ParamsStore, clusters: ClusterStore, cdn_clusters: CdnClusterStore, - cluster_params: ParamsStore, cdn_nodes: CdnNodeStore, nodes: NodeStore, accounts: AccountStore, @@ -111,11 +110,12 @@ pub mod ddc_bucket { .clusters .create( AccountId::default(), - &Vec::>::new(), - &Vec::::new(), + Vec::::new(), + Vec::>::new(), + Vec::::new(), + ClusterParams::from(""), ) .unwrap(); - let _ = contract.cluster_params.create("".to_string()).unwrap(); let _ = contract.buckets.create(AccountId::default(), 0); let _ = contract.bucket_params.create("".to_string()).unwrap(); }) @@ -458,10 +458,13 @@ pub mod ddc_bucket { v_nodes: Vec>, cdn_nodes_keys: Vec, cluster_params: ClusterParams, - ) -> ClusterId { - // self.message_cluster_create(nodes_keys, v_nodes, cdn_nodes_keys, cluster_params) - // .unwrap() - 1u32 + ) -> Result { + self.message_cluster_create( + nodes_keys, + v_nodes, + cdn_nodes_keys, + cluster_params + ) } /// Adds a Storage node to the targeting cluster. @@ -632,9 +635,8 @@ pub mod ddc_bucket { &mut self, cluster_id: ClusterId, cluster_params: ClusterParams - ) { - self.message_cluster_change_params(cluster_id, cluster_params) - .unwrap(); + ) -> Result<()> { + self.message_cluster_set_params(cluster_id, cluster_params) } /// Removes a cluster. @@ -1716,7 +1718,7 @@ pub mod ddc_bucket { NodeIsAddedToCluster(ClusterId), CdnNodeIsAddedToCluster(ClusterId), UnauthorizedNodeOwner, - UnauthorizedCdnNodeOwner + UnauthorizedCdnNodeOwner, } pub type Result = core::result::Result; From 90fbec4bc9263acd30f5b022d5c5d79394cbbda3 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Fri, 23 Jun 2023 00:04:10 +0200 Subject: [PATCH 13/89] feat(topology): adding and replacing storage nodes within a cluster --- bucket/ddc_bucket/cdn_cluster/entity.rs | 2 - bucket/ddc_bucket/cdn_node/entity.rs | 2 +- bucket/ddc_bucket/cluster/entity.rs | 73 ++---------- bucket/ddc_bucket/cluster/messages.rs | 115 +++++------------- bucket/ddc_bucket/cluster/store.rs | 6 - bucket/ddc_bucket/node/entity.rs | 2 +- bucket/ddc_bucket/node/store.rs | 1 + bucket/ddc_bucket/topology/store.rs | 148 ++++++++++++++---------- bucket/lib.rs | 46 +++----- 9 files changed, 146 insertions(+), 249 deletions(-) diff --git a/bucket/ddc_bucket/cdn_cluster/entity.rs b/bucket/ddc_bucket/cdn_cluster/entity.rs index f2be37ef..a1796c8a 100644 --- a/bucket/ddc_bucket/cdn_cluster/entity.rs +++ b/bucket/ddc_bucket/cdn_cluster/entity.rs @@ -12,8 +12,6 @@ use crate::ddc_bucket::params::store::Params; pub type ClusterId = u32; pub type ClusterParams = Params; -pub type VNodeIndex = u32; -pub type VNodeId = (ClusterId, VNodeIndex); #[derive(Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index 8884f306..c71daf2c 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -80,7 +80,7 @@ impl CdnNode { pub fn only_without_cluster(&self) -> Result<()> { if let Some(cluster_id) = self.cluster_id { - Err(CdnNodeIsAddedToCluster(cluster_id)) + Err(CdnNodeIsAlreadyAddedToCluster(cluster_id)) } else { Ok(()) } diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index a2330310..d7f26d2f 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -10,28 +10,27 @@ use crate::ddc_bucket::node::entity::{Resource, NodeKey}; use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; use crate::ddc_bucket::params::store::Params; +use crate::ddc_bucket::topology::store::VNodeToken; use crate::ddc_bucket::Error::UnauthorizedClusterManager; use crate::ddc_bucket::{AccountId, Balance, Error::InsufficientResources, Result}; pub type ClusterId = u32; pub type ClusterParams = Params; -pub type VNodeIndex = u32; -pub type VNodeId = (ClusterId, VNodeIndex); #[derive(Clone, PartialEq, Encode, Decode, SpreadAllocate, PackedLayout, SpreadLayout)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] pub struct Cluster { pub manager_id: AccountId, - + pub cluster_params: ClusterParams, + + // storage nodes pub nodes_keys: Vec, - pub v_nodes: Vec>, pub resource_per_vnode: Resource, pub resource_used: Resource, pub revenues: Cash, pub total_rent: Balance, - pub cluster_params: ClusterParams, - + // cdn nodes pub cdn_nodes_keys: Vec, pub cdn_resources_used: Resource, pub cdn_revenues: Cash, @@ -57,21 +56,17 @@ impl Cluster { pub fn new( manager_id: AccountId, - nodes_keys: Vec, - v_nodes: Vec>, - cdn_nodes_keys: Vec, cluster_params: ClusterParams, ) -> Self { Cluster { manager_id, - nodes_keys, - v_nodes, + cluster_params, + nodes_keys: Vec::new(), resource_per_vnode: 0, resource_used: 0, revenues: Cash(0), total_rent: 0, - cluster_params, - cdn_nodes_keys, + cdn_nodes_keys: Vec::new(), cdn_usd_per_gb: 104_857_600, // setting initially to 1 cent per GB cdn_resources_used: 0, cdn_revenues: Cash(0), @@ -95,58 +90,6 @@ impl Cluster { Ok(()) } - // v_nodes should be sorted - pub fn replace_v_node(&mut self, v_nodes: Vec, node_id: NodeKey) { - let old_v_nodes = &self.v_nodes; - let old_node_keys = &self.nodes_keys; - - let mut new_v_nodes = Vec::>::new(); - let mut new_node_keys = Vec::::new(); - - let mut new_v_nodes_idx = 0; - let mut v_nodes_for_new_node = Vec::::new(); - - for wrapper_idx in 0..old_v_nodes.len() { - let mut v_nodes_wrapper = Vec::::new(); - for idx in 0..old_v_nodes.get(wrapper_idx).unwrap().len() { - let new_v_node = match v_nodes.get(new_v_nodes_idx) { - Some(v) => *v, - None => 0, - }; - - if old_v_nodes - .get(wrapper_idx) - .unwrap() - .get(idx) - .unwrap() - .clone() - == new_v_node - { - v_nodes_for_new_node.push(new_v_node); - new_v_nodes_idx += 1; - } else { - v_nodes_wrapper.push( - old_v_nodes - .get(wrapper_idx) - .unwrap() - .get(idx) - .unwrap() - .clone(), - ); - } - } - - new_v_nodes.push(v_nodes_wrapper); - new_node_keys.push(*old_node_keys.get(wrapper_idx).unwrap()); - } - - new_v_nodes.push(v_nodes_for_new_node); - new_node_keys.push(node_id); - - self.v_nodes = new_v_nodes; - self.nodes_keys = new_node_keys; - } - pub fn only_manager(&self, caller: AccountId) -> Result<()> { if self.manager_id == caller { Ok(()) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index a487bf71..54621ab9 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -6,6 +6,7 @@ use crate::ddc_bucket::cash::{Cash, Payable}; use crate::ddc_bucket::cluster::entity::{Cluster, ClusterInfo}; use crate::ddc_bucket::node::entity::{Node, NodeKey, Resource}; use crate::ddc_bucket::cdn_node::entity::{CdnNode, CdnNodeKey}; +use crate::ddc_bucket::topology::store::{VNodeToken}; use crate::ddc_bucket::perm::entity::Permission; use crate::ddc_bucket::perm::store::PermStore; use crate::ddc_bucket::ClusterNodeReplaced; @@ -18,54 +19,23 @@ use crate::ddc_bucket::{ use super::entity::{ClusterId, ClusterParams}; impl DdcBucket { + pub fn message_cluster_create( &mut self, - nodes_keys: Vec, - v_nodes: Vec>, - cdn_nodes_keys: Vec, cluster_params: ClusterParams, ) -> Result { - let manager = Self::env().caller(); - - let mut nodes: Vec<(ink_env::AccountId, Node)> = Vec::<(NodeKey, Node)>::new(); - for node_key in &nodes_keys { - let node = self.nodes.get(*node_key)?; - node.only_without_cluster()?; - Self::only_trusted_manager(&self.perms, manager, node.provider_id.clone())?; - nodes.push((*node_key, node)); - } - - let mut cdn_nodes = Vec::<(CdnNodeKey, CdnNode)>::new(); - for cdn_node_key in &cdn_nodes_keys { - let cdn_node = self.cdn_nodes.get(*cdn_node_key)?; - cdn_node.only_without_cluster()?; - Self::only_trusted_manager(&self.perms, manager, cdn_node.provider_id.clone())?; - cdn_nodes.push((*cdn_node_key, cdn_node)); - } + let caller = Self::env().caller(); let cluster_id = self.clusters.create( - manager, - nodes_keys, - v_nodes.clone(), - cdn_nodes_keys, + caller, cluster_params.clone() )?; - let rent = self - .topology_store - .create_topology( - cluster_id, - v_nodes, - nodes.into_iter().map(|(key, node)| (key, node)).collect() - )?; - - let mut cluster = self.clusters.get(cluster_id)?; - cluster.set_rent(rent); - self.clusters.update(cluster_id, &cluster)?; + self.topology_store.create_topology(cluster_id)?; Self::env().emit_event(ClusterCreated { cluster_id, - manager, + manager: caller, cluster_params, }); @@ -75,40 +45,27 @@ impl DdcBucket { pub fn message_cluster_add_node( &mut self, cluster_id: ClusterId, - node_keys: Vec, - v_nodes: Vec>, + node_key: NodeKey, + v_nodes: Vec, ) -> Result<()> { - let manager = Self::env().caller(); - let mut nodes = Vec::<(NodeKey, Node)>::new(); + let caller = Self::env().caller(); - for node_key in &node_keys { - let node = self.nodes.get(*node_key)?; - // Verify that the node provider trusts the cluster manager. - Self::only_trusted_manager(&self.perms, manager, node.provider_id.clone())?; - nodes.push((*node_key, node)); - } + let mut node: Node = self.nodes.get(node_key)?; + node.only_without_cluster(); + Self::only_trusted_manager(&self.perms, caller, node.provider_id)?; - // add node and redistribute v_nodes - let cluster = self.clusters.get(cluster_id)?; + node.cluster_id = Some(cluster_id); + self.nodes.update(node_key, &node); - let mut old_v_nodes = Vec::::new(); - for v_nodes_per_phys_node in &cluster.v_nodes { - for v_node in v_nodes_per_phys_node { - old_v_nodes.push(*v_node); - } + let mut cluster: Cluster = self.clusters.get(cluster_id)?; + cluster.nodes_keys.push(node_key); + for v_node in v_nodes.iter() { + cluster.total_rent += node.rent_per_month; } - - // TODO: change v_nodes inside cluster entity - let total_rent = self - .topology_store - .add_node(cluster_id, &old_v_nodes, &v_nodes, nodes.into_iter().map(|(key, node)| (key, node)).collect())?; - - let mut cluster = self.clusters.get(cluster_id)?; - cluster.total_rent = total_rent as Balance; - cluster.v_nodes = v_nodes; - cluster.nodes_keys = node_keys; self.clusters.update(cluster_id, &cluster)?; + self.topology_store.add_node(cluster_id, node_key, v_nodes)?; + Ok(()) } @@ -122,13 +79,12 @@ impl DdcBucket { cluster.put_resource(resource); self.clusters.update(cluster_id, &cluster)?; - for v_nodes_wrapper in &cluster.v_nodes { - for &v_node in v_nodes_wrapper { - let node_key = self.topology_store.get(cluster_id, v_node)?; - let mut node = self.nodes.get(node_key)?; - node.take_resource(resource)?; - self.nodes.update(node_key, &node)?; - } + let cluster_vnodes = self.topology_store.get_vnodes_by_cluster(cluster_id)?; + for v_node in cluster_vnodes { + let node_key = self.topology_store.get_node_by_vnode(cluster_id, v_node)?; + let mut node = self.nodes.get(node_key)?; + node.take_resource(resource)?; + self.nodes.update(node_key, &node)?; } Self::env().emit_event(ClusterReserveResource { @@ -138,19 +94,18 @@ impl DdcBucket { Ok(()) } - // v_nodes length should be equal to v_nodes which were assigned to a physical node before pub fn message_cluster_replace_node( &mut self, cluster_id: ClusterId, v_nodes: Vec, new_node_key: NodeKey, ) -> Result<()> { - let mut cluster = self.clusters.get(cluster_id)?; + let cluster = self.clusters.get(cluster_id)?; let manager = Self::only_cluster_manager(&cluster)?; // Give back resources to the old node for all its v_nodes for v_node in v_nodes.clone() { - let old_node_key = self.topology_store.get(cluster_id, v_node)?; + let old_node_key = self.topology_store.get_node_by_vnode(cluster_id, v_node)?; // Give back resources to the old node let mut old_node = self.nodes.get(old_node_key)?; @@ -158,28 +113,21 @@ impl DdcBucket { self.nodes.update(old_node_key, &old_node)?; let mut new_node = self.nodes.get(new_node_key)?; - // Verify that the provider of the new node trusts the cluster manager. Self::only_trusted_manager(&self.perms, manager, new_node.provider_id)?; - // Reserve resources on the new node. new_node.take_resource(cluster.resource_per_vnode)?; self.nodes.update(new_node_key, &new_node)?; - - self.topology_store.save(cluster_id, v_node, new_node_key); } self.topology_store - .replace_node(cluster_id, v_nodes.clone(), new_node_key)?; - - cluster.replace_v_node(v_nodes, new_node_key); - - self.clusters.update(cluster_id, &cluster)?; + .replace_node(cluster_id, new_node_key, v_nodes)?; Self::env().emit_event(ClusterNodeReplaced { cluster_id, node_key: new_node_key, }); + Ok(()) } @@ -197,7 +145,8 @@ impl DdcBucket { )?; // Charge the provider payments from the cluster. - let num_shares = cluster.v_nodes.len() as Balance; + let cluster_vnodes = self.topology_store.get_vnodes_by_cluster(cluster_id)?; + let num_shares = cluster_vnodes.len() as Balance; let per_share = cluster.revenues.peek() / num_shares; cluster.revenues.pay(Payable(per_share * num_shares))?; diff --git a/bucket/ddc_bucket/cluster/store.rs b/bucket/ddc_bucket/cluster/store.rs index ca8498be..5557c1d0 100644 --- a/bucket/ddc_bucket/cluster/store.rs +++ b/bucket/ddc_bucket/cluster/store.rs @@ -21,9 +21,6 @@ impl ClusterStore { pub fn create( &mut self, manager_id: AccountId, - nodes_keys: Vec, - v_nodes: Vec>, - cdn_nodes_keys: Vec, cluster_params: ClusterParams, ) -> Result { let cluster_id = self.next_cluster_id; @@ -31,9 +28,6 @@ impl ClusterStore { let cluster = Cluster::new( manager_id, - nodes_keys, - v_nodes, - cdn_nodes_keys, cluster_params ); diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index 53a372a6..6f9d8f50 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -113,7 +113,7 @@ impl Node { pub fn only_without_cluster(&self) -> Result<()> { if let Some(cluster_id) = self.cluster_id { - Err(NodeIsAddedToCluster(cluster_id)) + Err(NodeIsAlreadyAddedToCluster(cluster_id)) } else { Ok(()) } diff --git a/bucket/ddc_bucket/node/store.rs b/bucket/ddc_bucket/node/store.rs index 6f6ed3b7..b9f403aa 100644 --- a/bucket/ddc_bucket/node/store.rs +++ b/bucket/ddc_bucket/node/store.rs @@ -63,4 +63,5 @@ impl NodeStore { self.keys.remove(pos); }; } + } diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index 34d14c42..5a4e50a4 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -4,92 +4,118 @@ use ink_storage::Mapping; use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; use crate::ddc_bucket::cluster::entity::ClusterId; -use crate::ddc_bucket::node::entity::{Node, NodeKey}; -use crate::ddc_bucket::Error::UnknownNode; -use crate::ddc_bucket::{Balance, Result, AccountId}; +use crate::ddc_bucket::node::entity::{NodeKey}; +use crate::ddc_bucket::{Error::*, Result}; + +pub type VNodeToken = u64; +pub type ClusterVNode = (ClusterId, VNodeToken); #[derive(SpreadAllocate, SpreadLayout, Default)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug,))] -pub struct TopologyStore(Mapping<(ClusterId, u64), NodeKey>); +#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] +pub struct TopologyStore { + // virtual nodes within a cluster + clusters_map: Mapping>, + // virtual nodes assigned to a physical node + nodes_map: Mapping>, + // physical node assigned to a virtual node + vnodes_map: Mapping, +} impl TopologyStore { - pub fn create_topology( - &mut self, - cluster_id: ClusterId, - v_nodes: Vec>, - nodes: Vec<(NodeKey, Node)>, - ) -> Result { - let mut total_rent = 0u128; - let mut vnodes_idx = 0; - - for node in &nodes { - let v_nodes_per_phys_node = &v_nodes[vnodes_idx as usize]; - for v_node in v_nodes_per_phys_node.iter() { - self.0.insert((cluster_id, *v_node), &(node.0)); - - total_rent += node.1.rent_per_month as Balance; - } + pub fn get_vnodes_by_cluster(&self, cluster_id: ClusterId) -> Result> { + self.clusters_map.get(cluster_id).ok_or(TopologyDoesNotExist) + } - vnodes_idx += 1; - } + pub fn get_vnodes_by_node(&self, node_key: NodeKey) -> Result> { + self.nodes_map.get(node_key).ok_or(VNodesDoNotExistsFor(node_key)) + } - Ok(total_rent) + pub fn get_node_by_vnode(&self, cluster_id: ClusterId, v_node: VNodeToken) -> Result { + self.vnodes_map.get((cluster_id, v_node)).ok_or(VNodeIsNotAssigned(cluster_id, v_node)) } - pub fn replace_node( + pub fn create_topology( &mut self, - cluster_id: u32, - v_nodes: Vec, - new_node_key: NodeKey, + cluster_id: ClusterId, ) -> Result<()> { - for v_node in v_nodes { - if self.0.contains(&(cluster_id, v_node)) { - self.0.insert(&(cluster_id, v_node), &new_node_key); - } else { - return Err(UnknownNode) - } + if self.clusters_map.contains(&cluster_id) { + Err(TopologyAlreadyExists) + } else { + let all_vnodes: Vec = Vec::new(); + self.clusters_map.insert(cluster_id, &all_vnodes); + Ok(()) } - - Ok(()) } pub fn add_node( &mut self, - cluster_id: u32, - old_v_nodes: &Vec, - v_nodes: &Vec>, - nodes: Vec<(NodeKey, Node)>, - ) -> Result { - // remove old nodes from topology - for &old_v_node in old_v_nodes { - self.0.insert((cluster_id, old_v_node), &AccountId::default()); // TODO: must be revised - } - - let mut total_rent = 0u32; - let mut index = 0u32; + cluster_id: ClusterId, + node_key: NodeKey, + v_nodes: Vec, + ) -> Result<()> { - // reassign v_nodes to physical ones - for node in nodes { - let v_nodes_per_phys_node = &v_nodes[index as usize]; + let mut all_vnodes = self.get_vnodes_by_cluster(cluster_id)?; - for v_node in v_nodes_per_phys_node.iter() { - self.0.insert((cluster_id, *v_node), &(node.0)); + for v_node in &v_nodes { - total_rent += node.1.rent_per_month as u32; + // vnode that is being added should not exist in the cluster topology + if let Some(node_key) = self.vnodes_map.get((cluster_id, v_node)) { + return Err(VNodeIsAlreadyAssignedTo(node_key)); } - index += 1; + // vnode that is being added should be assined to the physical node + self.vnodes_map.insert((cluster_id, v_node), &node_key); + + // vnode that is being added should be in added to the cluster topology + all_vnodes.push(*v_node); } - Ok(total_rent) - } + self.clusters_map.insert(cluster_id, &all_vnodes); + + // vnode that is being added should be assigned to the physical node + self.nodes_map.insert(node_key, &v_nodes); - pub fn get(&self, cluster_id: ClusterId, v_node: u64) -> Result { - self.0.get((cluster_id, v_node)).ok_or(UnknownNode) + Ok(()) } - pub fn save(&mut self, cluster_id: ClusterId, v_node: u64, node_id: NodeKey) { - self.0.insert(&(cluster_id, v_node), &node_id) + pub fn replace_node( + &mut self, + cluster_id: ClusterId, + new_node_key: NodeKey, + v_nodes: Vec, + ) -> Result<()> { + + let all_vnodes = self.get_vnodes_by_cluster(cluster_id)?; + + for v_node in &v_nodes { + + // vnode that is being reasigned should be in the cluster topology + if None == all_vnodes.iter().position(|x| *x == *v_node) { + return Err(VNodeDoesNotExists); + }; + + // vnode that is being reasigned should be already assigned to a physical node + let old_node_key = self.get_node_by_vnode(cluster_id, *v_node)?; + + // vnode that is being reasigned should be among other vnodes assigned to the old physical node + let mut old_node_vnodes = self.get_vnodes_by_node(old_node_key)?; + + // vnode that is being reasigned should be removed from the old physical node + if let Some(pos) = old_node_vnodes.iter().position(|x| *x == *v_node) { + old_node_vnodes.remove(pos); + }; + self.nodes_map.insert(old_node_key, &old_node_vnodes); + + // vnode that is being reasigned should be assined to the new physical node + self.vnodes_map.insert(&(cluster_id, *v_node), &new_node_key); + } + + // vnode that is being reasigned should be among other vnodes assigned to the new physical node + self.nodes_map.insert(new_node_key, &v_nodes); + + Ok(()) } + + } diff --git a/bucket/lib.rs b/bucket/lib.rs index fd60bc2a..cf721d1d 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -21,6 +21,7 @@ pub mod ddc_bucket { use node::{entity::*, store::*}; use params::store::*; use perm::store::*; + use topology::store::*; use crate::ddc_bucket::account::entity::Account; use crate::ddc_bucket::cdn_cluster::entity::CdnClusterStatus; @@ -110,9 +111,6 @@ pub mod ddc_bucket { .clusters .create( AccountId::default(), - Vec::::new(), - Vec::>::new(), - Vec::::new(), ClusterParams::from(""), ) .unwrap(); @@ -430,9 +428,6 @@ pub mod ddc_bucket { /// /// # Parameters /// - /// * `nodes_keys` - Public Keys of Storage nodes that are being added to the cluster. This param can accept up to 10 nodes per call. - /// * `v_nodes` - List of tokens (positions) related to Storage nodes from the `nodes_keys` param. The index of associated physical Storage node must be aligned with its virtual nodes list index. - /// * `cdn_nodes_keys` - Public Keys of Storage CDN that are being added to the cluster. This param can accept up to 10 nodes per call. /// * `cluster_params` - [Cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. /// /// # Output @@ -445,26 +440,13 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `ClusterManagerIsNotTrusted` error if the caller has a lack of trusted manager permissions for nodes he is trying to add. - /// * `NodeDoesNotExist` error if the adding Storage node does not exist. - /// * `InvalidVirtualNodes` error if there is a mismatch between adding Storage nodes and its virtual nodes. - /// * `CdnNodeDoesNotExist` error if the adding CDN node does not exist. - /// * `NodeIsAlreadyAddedToCluster(cluster_id)` error if an adding Storage node is already added to this or another cluster. - /// * `CdnNodeIsAlreadyAddedToCluster(cluster_id)` error if an adding CDN node is already added to this or another cluster. + /// * `InvalidClusterParams` error if there is an invalid cluster parameter. #[ink(message, payable)] pub fn cluster_create( &mut self, - nodes_keys: Vec, - v_nodes: Vec>, - cdn_nodes_keys: Vec, cluster_params: ClusterParams, ) -> Result { - self.message_cluster_create( - nodes_keys, - v_nodes, - cdn_nodes_keys, - cluster_params - ) + self.message_cluster_create(cluster_params) } /// Adds a Storage node to the targeting cluster. @@ -499,10 +481,9 @@ pub mod ddc_bucket { &mut self, cluster_id: ClusterId, node_key: NodeKey, - v_nodes: Vec, - ) { - // self.message_cluster_add_node(cluster_id, node_key, v_nodes) - // .unwrap() + v_nodes: Vec, + ) -> Result<()> { + self.message_cluster_add_node(cluster_id, node_key, v_nodes) } /// Removes a Storage node from the targeting cluster. @@ -1045,7 +1026,7 @@ pub mod ddc_bucket { /// /// * `UnauthorizedCdnNodeOwner` error if the caller is not the CDN node owner. /// * `CdnNodeDoesNotExist` error if the CDN node does not exist. - /// * `CdnNodeIsAddedToCluster(cluster_id)` error if the removing CDN node is added to some cluster. + /// * `CdnNodeIsAlreadyAddedToCluster(cluster_id)` error if the removing CDN node is added to some cluster. #[ink(message)] pub fn cdn_node_remove( &mut self, @@ -1228,7 +1209,7 @@ pub mod ddc_bucket { /// /// * `UnauthorizedNodeOwner` error if the caller is not the Storage node owner. /// * `NodeDoesNotExist` error if the Storage node does not exist. - /// * `NodeIsAddedToCluster(cluster_id)` error if the removing Storage node is added to some cluster. + /// * `NodeIsAlreadyAddedToCluster(cluster_id)` error if the removing Storage node is added to some cluster. #[ink(message)] pub fn node_remove( &mut self, @@ -1714,11 +1695,16 @@ pub mod ddc_bucket { InsufficientBalance, InsufficientResources, Unauthorized, - UnknownNode, - NodeIsAddedToCluster(ClusterId), - CdnNodeIsAddedToCluster(ClusterId), + NodeIsAlreadyAddedToCluster(ClusterId), + CdnNodeIsAlreadyAddedToCluster(ClusterId), UnauthorizedNodeOwner, UnauthorizedCdnNodeOwner, + TopologyAlreadyExists, + TopologyDoesNotExist, + VNodeIsNotAssigned(ClusterId, VNodeToken), + VNodeIsAlreadyAssignedTo(NodeKey), + VNodeDoesNotExists, + VNodesDoNotExistsFor(NodeKey) } pub type Result = core::result::Result; From 787c1e73bd7784a737bd9231cbaa56e5fa0e1da6 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Fri, 23 Jun 2023 14:55:20 +0200 Subject: [PATCH 14/89] feat(cluster): endpoint for replacing a storage node withing the cluster --- bucket/ddc_bucket/cluster/messages.rs | 61 +++++++++++--------- bucket/ddc_bucket/topology/store.rs | 10 ++-- bucket/lib.rs | 83 +++++++++++++++++++++------ 3 files changed, 104 insertions(+), 50 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 54621ab9..9154bb08 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -13,7 +13,7 @@ use crate::ddc_bucket::ClusterNodeReplaced; use crate::ddc_bucket::Error::{ClusterManagerIsNotTrusted, UnauthorizedClusterManager}; use crate::ddc_bucket::{ AccountId, Balance, ClusterCreated, ClusterDistributeRevenues, ClusterReserveResource, - DdcBucket, Result, + DdcBucket, Result, Error::* }; use super::entity::{ClusterId, ClusterParams}; @@ -53,6 +53,9 @@ impl DdcBucket { let mut node: Node = self.nodes.get(node_key)?; node.only_without_cluster(); Self::only_trusted_manager(&self.perms, caller, node.provider_id)?; + if node.cluster_id.is_some() { + return Err(NodeIsAlreadyAddedToCluster(node.cluster_id.unwrap())); + } node.cluster_id = Some(cluster_id); self.nodes.update(node_key, &node); @@ -69,31 +72,6 @@ impl DdcBucket { Ok(()) } - pub fn message_cluster_reserve_resource( - &mut self, - cluster_id: ClusterId, - resource: Resource, - ) -> Result<()> { - let mut cluster = self.clusters.get(cluster_id)?; - Self::only_cluster_manager(&cluster)?; - cluster.put_resource(resource); - self.clusters.update(cluster_id, &cluster)?; - - let cluster_vnodes = self.topology_store.get_vnodes_by_cluster(cluster_id)?; - for v_node in cluster_vnodes { - let node_key = self.topology_store.get_node_by_vnode(cluster_id, v_node)?; - let mut node = self.nodes.get(node_key)?; - node.take_resource(resource)?; - self.nodes.update(node_key, &node)?; - } - - Self::env().emit_event(ClusterReserveResource { - cluster_id, - resource, - }); - Ok(()) - } - pub fn message_cluster_replace_node( &mut self, cluster_id: ClusterId, @@ -113,6 +91,12 @@ impl DdcBucket { self.nodes.update(old_node_key, &old_node)?; let mut new_node = self.nodes.get(new_node_key)?; + let new_node_cluster_id = new_node.cluster_id + .ok_or_else(|| NodeIsNotAddedToCluster(cluster_id))?; + if new_node_cluster_id != cluster_id { + return Err(NodeIsAlreadyAddedToCluster(new_node_cluster_id)); + } + // Verify that the provider of the new node trusts the cluster manager. Self::only_trusted_manager(&self.perms, manager, new_node.provider_id)?; // Reserve resources on the new node. @@ -131,6 +115,31 @@ impl DdcBucket { Ok(()) } + pub fn message_cluster_reserve_resource( + &mut self, + cluster_id: ClusterId, + resource: Resource, + ) -> Result<()> { + let mut cluster = self.clusters.get(cluster_id)?; + Self::only_cluster_manager(&cluster)?; + cluster.put_resource(resource); + self.clusters.update(cluster_id, &cluster)?; + + let cluster_vnodes = self.topology_store.get_vnodes_by_cluster(cluster_id)?; + for v_node in cluster_vnodes { + let node_key = self.topology_store.get_node_by_vnode(cluster_id, v_node)?; + let mut node = self.nodes.get(node_key)?; + node.take_resource(resource)?; + self.nodes.update(node_key, &node)?; + } + + Self::env().emit_event(ClusterReserveResource { + cluster_id, + resource, + }); + Ok(()) + } + pub fn message_cluster_distribute_revenues(&mut self, cluster_id: ClusterId) -> Result<()> { let mut cluster = self.clusters.get(cluster_id)?; diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index 5a4e50a4..133f695d 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -24,15 +24,15 @@ pub struct TopologyStore { impl TopologyStore { pub fn get_vnodes_by_cluster(&self, cluster_id: ClusterId) -> Result> { - self.clusters_map.get(cluster_id).ok_or(TopologyDoesNotExist) + self.clusters_map.get(cluster_id).ok_or(NoVNodesInCluster(cluster_id)) } pub fn get_vnodes_by_node(&self, node_key: NodeKey) -> Result> { - self.nodes_map.get(node_key).ok_or(VNodesDoNotExistsFor(node_key)) + self.nodes_map.get(node_key).ok_or(PNodeHasNoVNodes(node_key)) } pub fn get_node_by_vnode(&self, cluster_id: ClusterId, v_node: VNodeToken) -> Result { - self.vnodes_map.get((cluster_id, v_node)).ok_or(VNodeIsNotAssigned(cluster_id, v_node)) + self.vnodes_map.get((cluster_id, v_node)).ok_or(VNodeHasNoPNode(cluster_id, v_node)) } pub fn create_topology( @@ -61,7 +61,7 @@ impl TopologyStore { // vnode that is being added should not exist in the cluster topology if let Some(node_key) = self.vnodes_map.get((cluster_id, v_node)) { - return Err(VNodeIsAlreadyAssignedTo(node_key)); + return Err(VNodeIsAlreadyAssignedToPNode(node_key)); } // vnode that is being added should be assined to the physical node @@ -92,7 +92,7 @@ impl TopologyStore { // vnode that is being reasigned should be in the cluster topology if None == all_vnodes.iter().position(|x| *x == *v_node) { - return Err(VNodeDoesNotExists); + return Err(VNodeDoesNotExistsInCluster(cluster_id)); }; // vnode that is being reasigned should be already assigned to a physical node diff --git a/bucket/lib.rs b/bucket/lib.rs index cf721d1d..3abff90c 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -471,11 +471,11 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. + /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. /// * `NodeDoesNotExist` error if the adding Storage node does not exist. - /// * `NodeIsAlreadyAddedToCluster(cluster_id)` error if the adding Storage node is already added to this or another cluster. + /// * `NodeIsAlreadyAddedToCluster(ClusterId)` error if the adding Storage node is already added to this or another cluster. #[ink(message, payable)] pub fn cluster_add_node( &mut self, @@ -506,11 +506,11 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. + /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. /// * `NodeDoesNotExist` error if the removing Storage node does not exist. - /// * `NodeIsNotInCluster` error if the removing Storage node is not in this cluster. + /// * `NodeIsNotAddedToCluster(ClusterId)` error if the removing Storage node is not in this cluster. #[ink(message)] pub fn cluster_remove_node( &mut self, @@ -521,6 +521,50 @@ pub mod ddc_bucket { // .unwrap() } + + /// Reasignes existing virtual nodes in the targeting cluster. + /// + /// This endpoint reasignes existing virtual nodes to another physical Storage node within the same cluster. + /// All specifying virtual nodes must pre-exist in the cluster and the new physical Storage node must be added to the cluster preliminary. + /// + /// # Parameters + /// + /// * `cluster_id` - ID of the targeting cluster. + /// * `v_nodes` - List of tokens (positions) to reasign for the new physical Storage node. + /// * `new_node_key` - Public Key associated with the Storage node that is being reasigned to the specified virtual nodes. + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Events + /// + /// * `ClusterNodeReplaced` event on successful virtual node reassignment. + /// + /// # Errors + /// + /// * `ClusterDoesNotExist` error if the cluster does not exist. + /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. + /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// * `NodeDoesNotExist` error if the new Storage node does not exist. + /// * `NodeIsNotAddedToCluster(ClusterId)` error if the new Storage node is not added to this cluster. + /// * `NodeIsAlreadyAddedToCluster(ClusterId)` error if the new Storage node is in another cluster. + /// * `VNodeHasNoPNode` error if the there is some virtual node that is being reasigned, but this virtual node is not assigned to any physical node. + /// * `VNodeIsAlreadyAssignedToPNode(NodeKey)` - error if there is some virtual node that is already assigned to other physical node within the same cluster. + #[ink(message)] + pub fn cluster_replace_node( + &mut self, + cluster_id: ClusterId, + v_nodes: Vec, + new_node_key: NodeKey, + ) -> Result<()> { + self.message_cluster_replace_node( + cluster_id, + v_nodes, + new_node_key + ) + } + /// Adds a CDN node to the targeting cluster. /// /// This endpoint adds a CDN node to the targeting cluster. @@ -541,11 +585,11 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. /// * `CdnNodeDoesNotExist` error if the adding CDN node does not exist. - /// * `CdnNodeIsAlreadyAddedToCluster(cluster_id)` error if the adding CDN node is already added to this or another cluster. + /// * `CdnNodeIsAlreadyAddedToCluster(ClusterId)` error if the adding CDN node is already added to this or another cluster. #[ink(message, payable)] pub fn cluster_add_cdn_node( &mut self, @@ -575,7 +619,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. /// * `CdnNodeDoesNotExist` error if the removing CDN node does not exist. @@ -609,7 +653,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. #[ink(message, payable)] pub fn cluster_set_params( @@ -639,7 +683,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `ClusterIsNotEmpty` error if the removing cluster contains some Storage or CDN nodes. #[ink(message)] @@ -670,10 +714,10 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. - /// * `NodeIsNotInCluster` error if the Storage node is not in this cluster. + /// * `NodeIsNotAddedToCluster(ClusterId)` error if the Storage node is not in this cluster. #[ink(message)] pub fn cluster_set_node_status( &mut self, @@ -704,7 +748,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedClusterOwner` error if the caller is not the cluster owner. + /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. /// * `CdnNodeIsNotInCluster` error if the Storage node is not in this cluster. @@ -1026,7 +1070,7 @@ pub mod ddc_bucket { /// /// * `UnauthorizedCdnNodeOwner` error if the caller is not the CDN node owner. /// * `CdnNodeDoesNotExist` error if the CDN node does not exist. - /// * `CdnNodeIsAlreadyAddedToCluster(cluster_id)` error if the removing CDN node is added to some cluster. + /// * `CdnNodeIsAlreadyAddedToCluster(ClusterId)` error if the removing CDN node is added to some cluster. #[ink(message)] pub fn cdn_node_remove( &mut self, @@ -1209,7 +1253,7 @@ pub mod ddc_bucket { /// /// * `UnauthorizedNodeOwner` error if the caller is not the Storage node owner. /// * `NodeDoesNotExist` error if the Storage node does not exist. - /// * `NodeIsAlreadyAddedToCluster(cluster_id)` error if the removing Storage node is added to some cluster. + /// * `NodeIsAlreadyAddedToCluster(ClusterId)` error if the removing Storage node is added to some cluster. #[ink(message)] pub fn node_remove( &mut self, @@ -1699,12 +1743,13 @@ pub mod ddc_bucket { CdnNodeIsAlreadyAddedToCluster(ClusterId), UnauthorizedNodeOwner, UnauthorizedCdnNodeOwner, + NodeIsNotAddedToCluster(ClusterId), TopologyAlreadyExists, - TopologyDoesNotExist, - VNodeIsNotAssigned(ClusterId, VNodeToken), - VNodeIsAlreadyAssignedTo(NodeKey), - VNodeDoesNotExists, - VNodesDoNotExistsFor(NodeKey) + NoVNodesInCluster(ClusterId), + VNodeDoesNotExistsInCluster(ClusterId), + VNodeHasNoPNode(ClusterId, VNodeToken), + VNodeIsAlreadyAssignedToPNode(NodeKey), + PNodeHasNoVNodes(NodeKey) } pub type Result = core::result::Result; From 557af5de091b81845517dceed03ec3ca549c870b Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Fri, 23 Jun 2023 18:10:52 +0200 Subject: [PATCH 15/89] feat(cluster): removing a node from a cluster --- bucket/ddc_bucket/cluster/messages.rs | 51 +++++++++++++++++------ bucket/ddc_bucket/node/entity.rs | 8 ++++ bucket/ddc_bucket/topology/store.rs | 60 +++++++++++++++++++++------ bucket/lib.rs | 17 ++++---- 4 files changed, 103 insertions(+), 33 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 9154bb08..27f4c37d 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -42,6 +42,7 @@ impl DdcBucket { Ok(cluster_id) } + pub fn message_cluster_add_node( &mut self, cluster_id: ClusterId, @@ -51,18 +52,15 @@ impl DdcBucket { let caller = Self::env().caller(); let mut node: Node = self.nodes.get(node_key)?; - node.only_without_cluster(); + node.only_without_cluster()?; Self::only_trusted_manager(&self.perms, caller, node.provider_id)?; - if node.cluster_id.is_some() { - return Err(NodeIsAlreadyAddedToCluster(node.cluster_id.unwrap())); - } node.cluster_id = Some(cluster_id); self.nodes.update(node_key, &node); let mut cluster: Cluster = self.clusters.get(cluster_id)?; cluster.nodes_keys.push(node_key); - for v_node in v_nodes.iter() { + for v_node in &v_nodes { cluster.total_rent += node.rent_per_month; } self.clusters.update(cluster_id, &cluster)?; @@ -72,6 +70,37 @@ impl DdcBucket { Ok(()) } + + pub fn message_cluster_remove_node( + &mut self, + cluster_id: ClusterId, + node_key: NodeKey, + ) -> Result<()> { + let caller = Self::env().caller(); + + let mut node: Node = self.nodes.get(node_key)?; + node.only_with_cluster(cluster_id)?; + Self::only_trusted_manager(&self.perms, caller, node.provider_id)?; + + node.cluster_id = None; + self.nodes.update(node_key, &node); + + let mut cluster: Cluster = self.clusters.get(cluster_id)?; + if let Some(pos) = cluster.nodes_keys.iter().position(|x| *x == node_key) { + cluster.nodes_keys.remove(pos); + } + let v_nodes = self.topology_store.get_vnodes_by_node(node_key)?; + for v_node in &v_nodes { + cluster.total_rent -= node.rent_per_month; + } + self.clusters.update(cluster_id, &cluster)?; + + self.topology_store.remove_node(cluster_id, node_key)?; + + Ok(()) + } + + pub fn message_cluster_replace_node( &mut self, cluster_id: ClusterId, @@ -82,8 +111,8 @@ impl DdcBucket { let manager = Self::only_cluster_manager(&cluster)?; // Give back resources to the old node for all its v_nodes - for v_node in v_nodes.clone() { - let old_node_key = self.topology_store.get_node_by_vnode(cluster_id, v_node)?; + for v_node in &v_nodes { + let old_node_key = self.topology_store.get_node_by_vnode(cluster_id, *v_node)?; // Give back resources to the old node let mut old_node = self.nodes.get(old_node_key)?; @@ -91,11 +120,7 @@ impl DdcBucket { self.nodes.update(old_node_key, &old_node)?; let mut new_node = self.nodes.get(new_node_key)?; - let new_node_cluster_id = new_node.cluster_id - .ok_or_else(|| NodeIsNotAddedToCluster(cluster_id))?; - if new_node_cluster_id != cluster_id { - return Err(NodeIsAlreadyAddedToCluster(new_node_cluster_id)); - } + new_node.only_with_cluster(cluster_id)?; // Verify that the provider of the new node trusts the cluster manager. Self::only_trusted_manager(&self.perms, manager, new_node.provider_id)?; @@ -115,6 +140,7 @@ impl DdcBucket { Ok(()) } + pub fn message_cluster_reserve_resource( &mut self, cluster_id: ClusterId, @@ -177,6 +203,7 @@ impl DdcBucket { Ok(()) } + pub fn message_cluster_set_params( &mut self, cluster_id: ClusterId, diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index 6f9d8f50..c40c5082 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -118,4 +118,12 @@ impl Node { Ok(()) } } + + pub fn only_with_cluster(&self, cluster_id: ClusterId) -> Result<()> { + if let Some(cluster_id) = self.cluster_id { + Ok(()) + } else { + Err(NodeIsNotAddedToCluster(cluster_id)) + } + } } diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index 133f695d..d9320af0 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -28,11 +28,11 @@ impl TopologyStore { } pub fn get_vnodes_by_node(&self, node_key: NodeKey) -> Result> { - self.nodes_map.get(node_key).ok_or(PNodeHasNoVNodes(node_key)) + self.nodes_map.get(node_key).ok_or(NodeHasNoAssignedVNodes(node_key)) } pub fn get_node_by_vnode(&self, cluster_id: ClusterId, v_node: VNodeToken) -> Result { - self.vnodes_map.get((cluster_id, v_node)).ok_or(VNodeHasNoPNode(cluster_id, v_node)) + self.vnodes_map.get((cluster_id, v_node)).ok_or(VNodeInNotAssignedToNode(cluster_id, v_node)) } pub fn create_topology( @@ -55,40 +55,76 @@ impl TopologyStore { v_nodes: Vec, ) -> Result<()> { - let mut all_vnodes = self.get_vnodes_by_cluster(cluster_id)?; + let mut all_vnodes: Vec = self.get_vnodes_by_cluster(cluster_id)?; for v_node in &v_nodes { // vnode that is being added should not exist in the cluster topology if let Some(node_key) = self.vnodes_map.get((cluster_id, v_node)) { - return Err(VNodeIsAlreadyAssignedToPNode(node_key)); + return Err(VNodeIsAlreadyAssignedToNode(node_key)); } - // vnode that is being added should be assined to the physical node + // vnode that is being added should be assigned to the physical node self.vnodes_map.insert((cluster_id, v_node), &node_key); - // vnode that is being added should be in added to the cluster topology + // vnode that is being added should be added to the cluster topology all_vnodes.push(*v_node); } self.clusters_map.insert(cluster_id, &all_vnodes); - // vnode that is being added should be assigned to the physical node + // vnodes that are being added should be assigned to the physical node self.nodes_map.insert(node_key, &v_nodes); Ok(()) } + + pub fn remove_node( + &mut self, + cluster_id: ClusterId, + node_key: NodeKey + ) -> Result<()> { + + let mut all_vnodes: Vec = self.get_vnodes_by_cluster(cluster_id)?; + let v_nodes = self.get_vnodes_by_node(node_key)?; + + for v_node in &v_nodes { + + // vnode that is being removed should exist in the cluster topology + if None == self.vnodes_map.get((cluster_id, *v_node)) { + return Err(VNodeInNotAssignedToNode(cluster_id, *v_node)); + } + + // vnode that is being removed should be unusigned from the physical node + self.vnodes_map.remove((cluster_id, v_node)); + + // vnode that is being removed should be removed from the cluster topology + if let Some(pos) = all_vnodes.iter().position(|x| *x == *v_node) { + all_vnodes.remove(pos); + }; + } + + self.clusters_map.insert(cluster_id, &all_vnodes); + + // vnodes that are being removed should be unusigned from the physical node + self.nodes_map.remove(node_key); + + Ok(()) + + } + + pub fn replace_node( &mut self, cluster_id: ClusterId, new_node_key: NodeKey, - v_nodes: Vec, + v_nodes_to_reasign: Vec, ) -> Result<()> { let all_vnodes = self.get_vnodes_by_cluster(cluster_id)?; - for v_node in &v_nodes { + for v_node in &v_nodes_to_reasign { // vnode that is being reasigned should be in the cluster topology if None == all_vnodes.iter().position(|x| *x == *v_node) { @@ -101,7 +137,7 @@ impl TopologyStore { // vnode that is being reasigned should be among other vnodes assigned to the old physical node let mut old_node_vnodes = self.get_vnodes_by_node(old_node_key)?; - // vnode that is being reasigned should be removed from the old physical node + // vnode that is being reasigned should be unasigned from the old physical node if let Some(pos) = old_node_vnodes.iter().position(|x| *x == *v_node) { old_node_vnodes.remove(pos); }; @@ -111,8 +147,8 @@ impl TopologyStore { self.vnodes_map.insert(&(cluster_id, *v_node), &new_node_key); } - // vnode that is being reasigned should be among other vnodes assigned to the new physical node - self.nodes_map.insert(new_node_key, &v_nodes); + // vnodes that are being reasigned should be among other vnodes assigned to the new physical node + self.nodes_map.insert(new_node_key, &v_nodes_to_reasign); Ok(()) } diff --git a/bucket/lib.rs b/bucket/lib.rs index 3abff90c..79ff9a84 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -516,9 +516,8 @@ pub mod ddc_bucket { &mut self, cluster_id: ClusterId, node_key: NodeKey, - ) { - // self.message_cluster_remove_node(cluster_id, node_key) - // .unwrap() + ) -> Result<()> { + self.message_cluster_remove_node(cluster_id, node_key) } @@ -549,8 +548,8 @@ pub mod ddc_bucket { /// * `NodeDoesNotExist` error if the new Storage node does not exist. /// * `NodeIsNotAddedToCluster(ClusterId)` error if the new Storage node is not added to this cluster. /// * `NodeIsAlreadyAddedToCluster(ClusterId)` error if the new Storage node is in another cluster. - /// * `VNodeHasNoPNode` error if the there is some virtual node that is being reasigned, but this virtual node is not assigned to any physical node. - /// * `VNodeIsAlreadyAssignedToPNode(NodeKey)` - error if there is some virtual node that is already assigned to other physical node within the same cluster. + /// * `VNodeInNotAssignedToNode(ClusterId, VNodeToken)` error if the there is some virtual node that is being reasigned, but this virtual node is not assigned to any physical node. + /// * `VNodeIsAlreadyAssignedToNode(NodeKey)` - error if there is some virtual node that is already assigned to other physical node within the same cluster. #[ink(message)] pub fn cluster_replace_node( &mut self, @@ -1739,17 +1738,17 @@ pub mod ddc_bucket { InsufficientBalance, InsufficientResources, Unauthorized, + NodeIsNotAddedToCluster(ClusterId), NodeIsAlreadyAddedToCluster(ClusterId), CdnNodeIsAlreadyAddedToCluster(ClusterId), UnauthorizedNodeOwner, UnauthorizedCdnNodeOwner, - NodeIsNotAddedToCluster(ClusterId), TopologyAlreadyExists, NoVNodesInCluster(ClusterId), VNodeDoesNotExistsInCluster(ClusterId), - VNodeHasNoPNode(ClusterId, VNodeToken), - VNodeIsAlreadyAssignedToPNode(NodeKey), - PNodeHasNoVNodes(NodeKey) + VNodeInNotAssignedToNode(ClusterId, VNodeToken), + VNodeIsAlreadyAssignedToNode(NodeKey), + NodeHasNoAssignedVNodes(NodeKey) } pub type Result = core::result::Result; From f1180b36d784aff4dd0bc787b39d796fbce7cbe6 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Sat, 24 Jun 2023 13:45:51 +0200 Subject: [PATCH 16/89] feat(cluster): adding cdn node --- bucket/ddc_bucket/cdn_node/entity.rs | 8 ++++++ bucket/ddc_bucket/cluster/messages.rs | 39 ++++++++++++++++++++++++++- bucket/lib.rs | 5 ++-- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index c71daf2c..ba329117 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -85,5 +85,13 @@ impl CdnNode { Ok(()) } } + + pub fn only_with_cluster(&self, cluster_id: ClusterId) -> Result<()> { + if let Some(cluster_id) = self.cluster_id { + Ok(()) + } else { + Err(CdnNodeIsNotAddedToCluster(cluster_id)) + } + } } \ No newline at end of file diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 27f4c37d..764e1f54 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -12,7 +12,8 @@ use crate::ddc_bucket::perm::store::PermStore; use crate::ddc_bucket::ClusterNodeReplaced; use crate::ddc_bucket::Error::{ClusterManagerIsNotTrusted, UnauthorizedClusterManager}; use crate::ddc_bucket::{ - AccountId, Balance, ClusterCreated, ClusterDistributeRevenues, ClusterReserveResource, + AccountId, Balance, ClusterCreated, ClusterNodeAdded, ClusterNodeRemoved, + ClusterCdnNodeAdded, ClusterDistributeRevenues, ClusterReserveResource, DdcBucket, Result, Error::* }; @@ -67,6 +68,11 @@ impl DdcBucket { self.topology_store.add_node(cluster_id, node_key, v_nodes)?; + Self::env().emit_event(ClusterNodeAdded { + cluster_id, + node_key + }); + Ok(()) } @@ -97,6 +103,11 @@ impl DdcBucket { self.topology_store.remove_node(cluster_id, node_key)?; + Self::env().emit_event(ClusterNodeRemoved { + cluster_id, + node_key + }); + Ok(()) } @@ -141,6 +152,32 @@ impl DdcBucket { } + pub fn message_cdn_cluster_add_cdn_node( + &mut self, + cluster_id: ClusterId, + cdn_node_key: CdnNodeKey, + ) -> Result<()> { + let manager = Self::env().caller(); + + let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; + cdn_node.only_without_cluster()?; + Self::only_trusted_manager(&self.perms, manager, cdn_node.provider_id)?; + + cdn_node.cluster_id = Some(cluster_id); + self.cdn_nodes.update(cdn_node_key, &cdn_node); + + let mut cluster: Cluster = self.clusters.get(cluster_id)?; + cluster.cdn_nodes_keys.push(cdn_node_key); + self.clusters.update(cluster_id, &cluster)?; + + Self::env().emit_event(ClusterCdnNodeAdded { + cluster_id, + cdn_node_key + }); + + Ok(()) + } + pub fn message_cluster_reserve_resource( &mut self, cluster_id: ClusterId, diff --git a/bucket/lib.rs b/bucket/lib.rs index 79ff9a84..308a5a22 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -594,8 +594,8 @@ pub mod ddc_bucket { &mut self, cluster_id: ClusterId, cdn_node_key: CdnNodeKey, - ) { - + ) -> Result<()> { + self.message_cdn_cluster_add_cdn_node(cluster_id, cdn_node_key) } /// Removes a CDN node from the targeting cluster. @@ -1740,6 +1740,7 @@ pub mod ddc_bucket { Unauthorized, NodeIsNotAddedToCluster(ClusterId), NodeIsAlreadyAddedToCluster(ClusterId), + CdnNodeIsNotAddedToCluster(ClusterId), CdnNodeIsAlreadyAddedToCluster(ClusterId), UnauthorizedNodeOwner, UnauthorizedCdnNodeOwner, From 3447778161c65d9790a7e26ae143e08ea943aa68 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Sat, 24 Jun 2023 13:53:57 +0200 Subject: [PATCH 17/89] feat(cluster): removing cdn node --- bucket/ddc_bucket/cluster/messages.rs | 37 ++++++++++++++++++++++++--- bucket/lib.rs | 10 ++++---- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 764e1f54..6bf58b76 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -13,7 +13,7 @@ use crate::ddc_bucket::ClusterNodeReplaced; use crate::ddc_bucket::Error::{ClusterManagerIsNotTrusted, UnauthorizedClusterManager}; use crate::ddc_bucket::{ AccountId, Balance, ClusterCreated, ClusterNodeAdded, ClusterNodeRemoved, - ClusterCdnNodeAdded, ClusterDistributeRevenues, ClusterReserveResource, + ClusterCdnNodeAdded, ClusterCdnNodeRemoved, ClusterDistributeRevenues, ClusterReserveResource, DdcBucket, Result, Error::* }; @@ -21,6 +21,7 @@ use super::entity::{ClusterId, ClusterParams}; impl DdcBucket { + pub fn message_cluster_create( &mut self, cluster_params: ClusterParams, @@ -152,14 +153,14 @@ impl DdcBucket { } - pub fn message_cdn_cluster_add_cdn_node( + pub fn message_cluster_add_cdn_node( &mut self, cluster_id: ClusterId, cdn_node_key: CdnNodeKey, ) -> Result<()> { let manager = Self::env().caller(); - let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; + let mut cdn_node: CdnNode = self.cdn_nodes.get(cdn_node_key)?; cdn_node.only_without_cluster()?; Self::only_trusted_manager(&self.perms, manager, cdn_node.provider_id)?; @@ -178,6 +179,36 @@ impl DdcBucket { Ok(()) } + + pub fn message_cluster_remove_cdn_node( + &mut self, + cluster_id: ClusterId, + cdn_node_key: CdnNodeKey, + ) -> Result<()> { + let caller = Self::env().caller(); + + let mut cdn_node: CdnNode = self.cdn_nodes.get(cdn_node_key)?; + cdn_node.only_with_cluster(cluster_id)?; + Self::only_trusted_manager(&self.perms, caller, cdn_node.provider_id)?; + + cdn_node.cluster_id = None; + self.cdn_nodes.update(cdn_node_key, &cdn_node); + + let mut cluster: Cluster = self.clusters.get(cluster_id)?; + if let Some(pos) = cluster.cdn_nodes_keys.iter().position(|x| *x == cdn_node_key) { + cluster.cdn_nodes_keys.remove(pos); + } + self.clusters.update(cluster_id, &cluster)?; + + Self::env().emit_event(ClusterCdnNodeRemoved { + cluster_id, + cdn_node_key + }); + + Ok(()) + } + + pub fn message_cluster_reserve_resource( &mut self, cluster_id: ClusterId, diff --git a/bucket/lib.rs b/bucket/lib.rs index 308a5a22..cb6df34f 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -595,7 +595,7 @@ pub mod ddc_bucket { cluster_id: ClusterId, cdn_node_key: CdnNodeKey, ) -> Result<()> { - self.message_cdn_cluster_add_cdn_node(cluster_id, cdn_node_key) + self.message_cluster_add_cdn_node(cluster_id, cdn_node_key) } /// Removes a CDN node from the targeting cluster. @@ -622,14 +622,14 @@ pub mod ddc_bucket { /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. /// * `CdnNodeDoesNotExist` error if the removing CDN node does not exist. - /// * `CdnNodeIsNotInCluster` error if the removing CDN node is not in this cluster. + /// * `CdnNodeIsNotAddedToCluster(ClusterId)` error if the removing CDN node is not in this cluster. #[ink(message)] pub fn cluster_remove_cdn_node( &mut self, cluster_id: ClusterId, cdn_node_key: CdnNodeKey, - ) { - + ) -> Result<()> { + self.message_cluster_remove_cdn_node(cluster_id, cdn_node_key) } /// Sets parameters for the targeting cluster. @@ -750,7 +750,7 @@ pub mod ddc_bucket { /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. - /// * `CdnNodeIsNotInCluster` error if the Storage node is not in this cluster. + /// * `CdnNodeIsNotAddedToCluster(ClusterId)` error if the CDN node is not in this cluster. #[ink(message)] pub fn cluster_set_cdn_node_status( &mut self, From f79f60a126898b34b6e91072d5528cd0a26ae0dc Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Sat, 24 Jun 2023 15:11:11 +0200 Subject: [PATCH 18/89] feat(cluster): cdn cluster is removed --- bucket/ddc_bucket/cdn_cluster/entity.rs | 84 --------- bucket/ddc_bucket/cdn_cluster/messages.rs | 209 ---------------------- bucket/ddc_bucket/cdn_cluster/mod.rs | 5 - bucket/ddc_bucket/cdn_cluster/store.rs | 37 ---- bucket/ddc_bucket/cdn_node/entity.rs | 3 +- bucket/ddc_bucket/cdn_node/store.rs | 3 +- bucket/ddc_bucket/cluster/entity.rs | 37 +++- bucket/ddc_bucket/cluster/messages.rs | 161 ++++++++++++++++- bucket/ddc_bucket/cluster/store.rs | 6 +- bucket/ddc_bucket/node/entity.rs | 3 +- bucket/ddc_bucket/node/store.rs | 3 +- bucket/lib.rs | 8 +- 12 files changed, 194 insertions(+), 365 deletions(-) delete mode 100644 bucket/ddc_bucket/cdn_cluster/entity.rs delete mode 100644 bucket/ddc_bucket/cdn_cluster/messages.rs delete mode 100644 bucket/ddc_bucket/cdn_cluster/mod.rs delete mode 100644 bucket/ddc_bucket/cdn_cluster/store.rs diff --git a/bucket/ddc_bucket/cdn_cluster/entity.rs b/bucket/ddc_bucket/cdn_cluster/entity.rs deleted file mode 100644 index a1796c8a..00000000 --- a/bucket/ddc_bucket/cdn_cluster/entity.rs +++ /dev/null @@ -1,84 +0,0 @@ -//! The data structure of Clusters. - -use ink_prelude::vec::Vec; -use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout, PackedAllocate}; -use scale::{Decode, Encode}; -use ink_primitives::Key; -use crate::ddc_bucket::{AccountId, Balance, Result}; -use crate::ddc_bucket::cash::{Cash, Payable}; -use crate::ddc_bucket::Error::{UnauthorizedClusterManager, InsufficientBalance}; -use crate::ddc_bucket::cdn_node::entity::{Resource, CdnNodeKey}; -use crate::ddc_bucket::params::store::Params; - -pub type ClusterId = u32; -pub type ClusterParams = Params; - -#[derive(Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] -#[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] -pub struct CdnCluster { - pub manager_id: AccountId, - pub cdn_nodes: Vec, - pub resources_used: Resource, - pub revenues: Cash, - pub usd_per_gb: Balance, -} - -// https://use.ink/3.x/ink-vs-solidity#nested-mappings--custom--advanced-structures -#[allow(unconditional_recursion)] -impl ink_storage::traits::PackedAllocate for CdnCluster { - fn allocate_packed(&mut self, at: &Key) { - PackedAllocate::allocate_packed(&mut *self, at) - } -} - -#[derive(Clone, PartialEq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] -pub struct CdnClusterStatus { - pub cluster_id: ClusterId, - pub cluster: CdnCluster, -} - -impl CdnCluster { - pub fn new( - manager_id: AccountId, - cdn_nodes: Vec, - ) -> Self { - CdnCluster { - manager_id, - cdn_nodes, - // usd_per_gb: 100_000_000, // setting initially to 1 cent per GB - usd_per_gb: 104_857_600, // setting initially to 1 cent per GB - resources_used: 0, - revenues: Cash(0), - } - } - - pub fn get_revenue_cere(&self) -> Cash { - self.revenues - } - - pub fn set_rate(&mut self, usd_per_gb: Balance) -> Result<()> { - self.usd_per_gb = usd_per_gb; - Ok(()) - } - - pub fn get_rate(&self) -> Balance { - self.usd_per_gb - } - - pub fn put_revenues(&mut self, amount: Cash) { - self.revenues.increase(amount); - } - - pub fn take_revenues(&mut self, amount: Payable) -> Result<()> { - if amount.peek() > self.revenues.peek() { - return Err(InsufficientBalance); - } - self.revenues.pay_unchecked(amount); - Ok(()) - } - - pub fn only_manager(&self, caller: AccountId) -> Result<()> { - if self.manager_id == caller { Ok(()) } else { Err(UnauthorizedClusterManager) } - } -} diff --git a/bucket/ddc_bucket/cdn_cluster/messages.rs b/bucket/ddc_bucket/cdn_cluster/messages.rs deleted file mode 100644 index 90ded167..00000000 --- a/bucket/ddc_bucket/cdn_cluster/messages.rs +++ /dev/null @@ -1,209 +0,0 @@ -//! The public interface to manage Clusters. - -use ink_lang::codegen::{EmitEvent, StaticEnv}; -use ink_prelude::vec::Vec; - -use crate::ddc_bucket::{AccountId, Balance, BucketId, CdnClusterCreated, ClusterDistributeRevenues, ClusterId, DdcBucket, Result}; -use crate::ddc_bucket::cash::{Cash, Payable}; -use crate::ddc_bucket::cdn_cluster::entity::{CdnCluster, CdnClusterStatus}; -use crate::ddc_bucket::Error::{ClusterManagerIsNotTrusted, UnauthorizedClusterManager, InsufficientBalance}; -use crate::ddc_bucket::cdn_node::entity::{CdnNode, CdnNodeKey, Resource}; -use crate::ddc_bucket::perm::entity::Permission; -use crate::ddc_bucket::perm::store::PermStore; - -const KB_PER_GB: Balance = 1_000_000; - -impl DdcBucket { - pub fn message_cdn_cluster_create( - &mut self, - cdn_nodes_keys: Vec, - ) -> Result { - let manager = Self::env().caller(); - - let mut cdn_nodes = Vec::<(CdnNodeKey, CdnNode)>::new(); - for cdn_node_key in &cdn_nodes_keys { - let cdn_node = self.cdn_nodes.get(*cdn_node_key)?; - // Verify that the node provider trusts the cluster manager. - Self::only_cdn_trusted_manager(&self.perms, manager, cdn_node.provider_id.clone())?; - - cdn_nodes.push((*cdn_node_key, cdn_node)); - } - - let cluster_id = self.cdn_clusters.create(manager, cdn_nodes_keys)?; - - Self::env().emit_event(CdnClusterCreated { - cluster_id, - manager - }); - - Ok(cluster_id) - } - - // Set the price usd per gb - pub fn message_cdn_set_rate(&mut self, cluster_id: ClusterId, usd_per_gb: u128) -> Result<()> { - let cluster = self.cdn_clusters.get_mut(cluster_id)?; - Self::only_cdn_cluster_manager(cluster)?; - - cluster.set_rate(usd_per_gb)?; - - Ok(()) - } - - // Get the price usd per gb - pub fn message_cdn_get_rate(&self, cluster_id: ClusterId) -> Result { - let cluster = self.cdn_clusters.get(cluster_id)?; - let rate = cluster.get_rate(); - Ok(rate) - } - - // First payment is for aggregate consumption for account, second is the aggregate payment for the node (u32 for ids) - pub fn message_cdn_cluster_put_revenue(&mut self, cluster_id: ClusterId, aggregates_accounts: Vec<(AccountId, u128)>, aggregates_nodes: Vec<(CdnNodeKey, u128)>, aggregates_buckets: Vec<(BucketId, Resource)>, era: u64) -> Result<()> { - let cluster = self.cdn_clusters.get_mut(cluster_id)?; - // Self::only_cdn_cluster_manager(cluster)?; - - let mut cluster_payment = 0; - let mut _undistributed_payment_accounts = 0; - - let aggregate_payments_accounts; - { - let conv = &self.accounts.1; - aggregate_payments_accounts = aggregates_accounts.iter().map(|(client_id, resources_used)| { - let account_id = *client_id; - let cere_payment: Balance = conv.to_cere(*resources_used as Balance * cluster.usd_per_gb / KB_PER_GB ); - (account_id, cere_payment) - }).collect::>(); - } - - for &(client_id, payment) in aggregate_payments_accounts.iter() { - if let Ok(mut account) = self.accounts.get(&client_id) { - account.withdraw_bonded(Payable(payment))?; - _undistributed_payment_accounts += payment; - self.accounts.save(&client_id, &account); - } else { - return Err(InsufficientBalance) - } - }; - - - let conv = &self.accounts.1; - let committer = &mut self.committer_store; - - for &(cdn_node_key, resources_used) in aggregates_nodes.iter() { - let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; - let protocol_fee = self.protocol_store.get_fee_bp(); - let protocol = &mut self.protocol_store; - - let payment = conv.to_cere (resources_used as Balance * cluster.usd_per_gb / KB_PER_GB ); - - // let protocol_payment = payment * protocol_fee as u128/ 10_000; - let node_payment = payment * (10_000 - protocol_fee) as u128 / 10_000; - let protocol_payment = payment - node_payment; - - cdn_node.put_payment(node_payment); - - protocol.put_revenues(Cash(protocol_payment)); - self.cdn_nodes.update(cdn_node_key, &cdn_node)?; - - committer.set_validated_commit(cdn_node_key, era).unwrap(); - cluster_payment += node_payment; - } - // Add check that two payments should equal? - - // Go through buckets and deduct used resources - for &(bucket_id, resources_used) in aggregates_buckets.iter() { - let bucket = self.buckets.get_mut(bucket_id)?; - - if bucket.resource_consumption_cap <= resources_used { - bucket.resource_consumption_cap -= resources_used; - } - } - - // Add revenues to cluster - cluster.put_revenues(Cash(cluster_payment)); - - Ok(()) - } - - pub fn message_cdn_cluster_distribute_revenues(&mut self, cluster_id: ClusterId) -> Result<()> { - let cluster = self.cdn_clusters.get_mut(cluster_id)?; - - // Charge the network fee from the cluster. - Self::capture_network_fee(&self.network_fee, &mut cluster.revenues)?; - - // Charge the cluster management fee. - Self::capture_fee( - self.network_fee.cluster_management_fee_bp(), - cluster.manager_id, - &mut cluster.revenues)?; - - // First accumulated revenues to distribute. - let mut distributed_revenue = 0; - - for cdn_node_key in &cluster.cdn_nodes { - let cdn_node = self.cdn_nodes.get(*cdn_node_key)?; - distributed_revenue += cdn_node.undistributed_payment; - } - - // Charge the provider payments from the cluster. - cluster.revenues.pay(Payable(distributed_revenue))?; - - // Distribute revenues to nodes - for cdn_node_key in &cluster.cdn_nodes { - let mut cdn_node = self.cdn_nodes.get(*cdn_node_key)?; - - Self::send_cash(cdn_node.provider_id, Cash(cdn_node.undistributed_payment))?; - cdn_node.take_payment(cdn_node.undistributed_payment)?; - self.cdn_nodes.update(*cdn_node_key, &cdn_node)?; - - Self::env().emit_event(ClusterDistributeRevenues { - cluster_id, - provider_id: cdn_node.provider_id - }); - } - - Ok(()) - } - - pub fn message_cdn_cluster_get(&self, cluster_id: ClusterId) -> Result { - let cluster = self.cdn_clusters.get(cluster_id)?.clone(); - Ok(CdnClusterStatus { cluster_id, cluster }) - } - - pub fn message_cdn_cluster_list(&self, offset: u32, limit: u32, filter_manager_id: Option) -> (Vec, u32) { - let mut clusters = Vec::with_capacity(limit as usize); - for cluster_id in offset..offset + limit { - let cluster = match self.cdn_clusters.0.get(cluster_id as usize) { - None => break, // No more items, stop. - Some(cluster) => cluster, - }; - // Apply the filter if given. - if let Some(manager_id) = filter_manager_id { - if manager_id != cluster.manager_id { - continue; // Skip non-matches. - } - } - // Include the complete status of matched items. - let status = CdnClusterStatus { - cluster_id, - cluster: cluster.clone(), - }; - clusters.push(status); - } - (clusters, self.cdn_clusters.0.len().try_into().unwrap()) - } - - fn only_cdn_cluster_manager(cluster: &CdnCluster) -> Result { - let caller = Self::env().caller(); - if caller == cluster.manager_id { - Ok(caller) - } else { - Err(UnauthorizedClusterManager) - } - } - - fn only_cdn_trusted_manager(perm_store: &PermStore, manager: AccountId, trusted_by: AccountId) -> Result<()> { - let perm = Permission::ManagerTrustedBy(trusted_by); - let trusts = perm_store.has_permission(manager, perm); - if trusts { Ok(()) } else { Err(ClusterManagerIsNotTrusted) } - } -} diff --git a/bucket/ddc_bucket/cdn_cluster/mod.rs b/bucket/ddc_bucket/cdn_cluster/mod.rs deleted file mode 100644 index e896ccbb..00000000 --- a/bucket/ddc_bucket/cdn_cluster/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! CDN Cluster management. - -pub mod entity; -pub mod store; -pub mod messages; \ No newline at end of file diff --git a/bucket/ddc_bucket/cdn_cluster/store.rs b/bucket/ddc_bucket/cdn_cluster/store.rs deleted file mode 100644 index 88f0ece7..00000000 --- a/bucket/ddc_bucket/cdn_cluster/store.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! The store where to create and access Clusters by ID. - -use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; -use ink_prelude::vec::Vec; - -use crate::ddc_bucket::{AccountId, Error::*, Result}; -use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; -use super::entity::{CdnCluster, ClusterId}; - -pub const MAX_VNODES: u32 = 300; - -#[derive(SpreadAllocate, SpreadLayout, Default)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] -pub struct CdnClusterStore(pub Vec); - -impl CdnClusterStore { - pub fn create( - &mut self, - manager_id: AccountId, - cdn_nodes_keys: Vec, - ) -> Result { - let cluster = CdnCluster::new(manager_id, cdn_nodes_keys); - - let cluster_id: ClusterId = self.0.len().try_into().unwrap(); - self.0.push(cluster); - - Ok(cluster_id) - } - - pub fn get(&self, cluster_id: ClusterId) -> Result<&CdnCluster> { - self.0.get(cluster_id as usize).ok_or(ClusterDoesNotExist) - } - - pub fn get_mut(&mut self, cluster_id: ClusterId) -> Result<&mut CdnCluster> { - self.0.get_mut(cluster_id as usize).ok_or(ClusterDoesNotExist) - } -} diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index ba329117..f71cfede 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -39,7 +39,6 @@ pub struct CdnNodeInfo { impl CdnNode { pub fn new( - cdn_node_key: CdnNodeKey, provider_id: AccountId, cdn_node_params: CdnNodeParams, undistributed_payment: Balance @@ -87,7 +86,7 @@ impl CdnNode { } pub fn only_with_cluster(&self, cluster_id: ClusterId) -> Result<()> { - if let Some(cluster_id) = self.cluster_id { + if let Some(_) = self.cluster_id { Ok(()) } else { Err(CdnNodeIsNotAddedToCluster(cluster_id)) diff --git a/bucket/ddc_bucket/cdn_node/store.rs b/bucket/ddc_bucket/cdn_node/store.rs index 1ff2e114..e722265a 100644 --- a/bucket/ddc_bucket/cdn_node/store.rs +++ b/bucket/ddc_bucket/cdn_node/store.rs @@ -4,7 +4,7 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; use ink_storage::Mapping; use ink_prelude::vec::Vec; -use crate::ddc_bucket::{AccountId, Balance, NodeStatus, Error::*, Result}; +use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; use super::entity::{CdnNode, CdnNodeKey, CdnNodeParams}; @@ -29,7 +29,6 @@ impl CdnNodeStore { Err(CdnNodeAlreadyExists) } else { let cdn_node = CdnNode::new( - cdn_node_key, provider_id, cdn_node_params, undistributed_payment diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index d7f26d2f..cd294a66 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -5,13 +5,12 @@ use ink_prelude::vec::Vec; use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout, PackedAllocate}; use scale::{Decode, Encode}; use ink_primitives::Key; -use crate::ddc_bucket::cash::Cash; +use crate::ddc_bucket::cash::{Cash, Payable}; use crate::ddc_bucket::node::entity::{Resource, NodeKey}; use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; use crate::ddc_bucket::params::store::Params; -use crate::ddc_bucket::topology::store::VNodeToken; -use crate::ddc_bucket::Error::UnauthorizedClusterManager; +use crate::ddc_bucket::Error::{UnauthorizedClusterManager, InsufficientBalance}; use crate::ddc_bucket::{AccountId, Balance, Error::InsufficientResources, Result}; pub type ClusterId = u32; @@ -74,7 +73,12 @@ impl Cluster { } pub fn get_rent(&self, resource: Resource) -> Balance { - return self.total_rent * resource as Balance; + let rent = self.total_rent * resource as Balance; + rent + } + + pub fn set_rent(&mut self, rent: Balance) { + self.total_rent = rent; } pub fn put_resource(&mut self, amount: Resource) { @@ -98,7 +102,28 @@ impl Cluster { } } - pub fn set_rent(&mut self, rent: Balance) { - self.total_rent = rent; + pub fn cdn_get_revenue_cere(&self) -> Cash { + self.cdn_revenues + } + + pub fn cdn_set_rate(&mut self, cdn_usd_per_gb: Balance) { + self.cdn_usd_per_gb = cdn_usd_per_gb; } + + pub fn cdn_get_rate(&self) -> Balance { + self.cdn_usd_per_gb + } + + pub fn cdn_put_revenues(&mut self, amount: Cash) { + self.cdn_revenues.increase(amount); + } + + pub fn cdn_take_revenues(&mut self, amount: Payable) -> Result<()> { + if amount.peek() > self.cdn_revenues.peek() { + return Err(InsufficientBalance); + } + self.cdn_revenues.pay_unchecked(amount); + Ok(()) + } + } diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 6bf58b76..0d609f49 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -4,6 +4,7 @@ use ink_prelude::vec::Vec; use crate::ddc_bucket::cash::{Cash, Payable}; use crate::ddc_bucket::cluster::entity::{Cluster, ClusterInfo}; +use crate::ddc_bucket::bucket::entity::{BucketId}; use crate::ddc_bucket::node::entity::{Node, NodeKey, Resource}; use crate::ddc_bucket::cdn_node::entity::{CdnNode, CdnNodeKey}; use crate::ddc_bucket::topology::store::{VNodeToken}; @@ -19,6 +20,8 @@ use crate::ddc_bucket::{ use super::entity::{ClusterId, ClusterParams}; +const KB_PER_GB: Balance = 1_000_000; + impl DdcBucket { @@ -58,7 +61,7 @@ impl DdcBucket { Self::only_trusted_manager(&self.perms, caller, node.provider_id)?; node.cluster_id = Some(cluster_id); - self.nodes.update(node_key, &node); + self.nodes.update(node_key, &node)?; let mut cluster: Cluster = self.clusters.get(cluster_id)?; cluster.nodes_keys.push(node_key); @@ -90,7 +93,7 @@ impl DdcBucket { Self::only_trusted_manager(&self.perms, caller, node.provider_id)?; node.cluster_id = None; - self.nodes.update(node_key, &node); + self.nodes.update(node_key, &node)?; let mut cluster: Cluster = self.clusters.get(cluster_id)?; if let Some(pos) = cluster.nodes_keys.iter().position(|x| *x == node_key) { @@ -165,7 +168,7 @@ impl DdcBucket { Self::only_trusted_manager(&self.perms, manager, cdn_node.provider_id)?; cdn_node.cluster_id = Some(cluster_id); - self.cdn_nodes.update(cdn_node_key, &cdn_node); + self.cdn_nodes.update(cdn_node_key, &cdn_node)?; let mut cluster: Cluster = self.clusters.get(cluster_id)?; cluster.cdn_nodes_keys.push(cdn_node_key); @@ -192,7 +195,7 @@ impl DdcBucket { Self::only_trusted_manager(&self.perms, caller, cdn_node.provider_id)?; cdn_node.cluster_id = None; - self.cdn_nodes.update(cdn_node_key, &cdn_node); + self.cdn_nodes.update(cdn_node_key, &cdn_node)?; let mut cluster: Cluster = self.clusters.get(cluster_id)?; if let Some(pos) = cluster.cdn_nodes_keys.iter().position(|x| *x == cdn_node_key) { @@ -234,6 +237,7 @@ impl DdcBucket { Ok(()) } + pub fn message_cluster_distribute_revenues(&mut self, cluster_id: ClusterId) -> Result<()> { let mut cluster = self.clusters.get(cluster_id)?; @@ -285,6 +289,7 @@ impl DdcBucket { Ok(()) } + pub fn message_cluster_get(&self, cluster_id: ClusterId) -> Result { let cluster = self.clusters.get(cluster_id)?.clone(); Ok(ClusterInfo { @@ -293,6 +298,7 @@ impl DdcBucket { }) } + pub fn message_cluster_list( &self, offset: u32, @@ -321,6 +327,150 @@ impl DdcBucket { (clusters, self.clusters.next_cluster_id - 1) } + + // Set the price usd per gb + pub fn message_cdn_set_rate( + &mut self, + cluster_id: ClusterId, + cdn_usd_per_gb: Balance + ) -> Result<()> { + let caller = Self::env().caller(); + + let mut cluster = self.clusters.get(cluster_id)?; + cluster.only_manager(caller)?; + cluster.cdn_set_rate(cdn_usd_per_gb); + self.clusters.update(cluster_id, &cluster)?; + + Ok(()) + } + + + // Get the price usd per gb + pub fn message_cdn_get_rate(&self, cluster_id: ClusterId) -> Result { + let cluster = self.clusters.get(cluster_id)?; + let rate = cluster.cdn_get_rate(); + Ok(rate) + } + + + // First payment is for aggregate consumption for account, second is the aggregate payment for the node (u32 for ids) + pub fn message_cdn_cluster_put_revenue( + &mut self, + cluster_id: ClusterId, + aggregates_accounts: Vec<(AccountId, u128)>, + aggregates_nodes: Vec<(CdnNodeKey, u128)>, + aggregates_buckets: Vec<(BucketId, Resource)>, + era: u64 + ) -> Result<()> { + let mut cluster = self.clusters.get(cluster_id)?; + // Self::only_cdn_cluster_manager(cluster)?; + + let mut cluster_payment = 0; + let mut _undistributed_payment_accounts = 0; + + let aggregate_payments_accounts; + { + let conv = &self.accounts.1; + aggregate_payments_accounts = aggregates_accounts.iter().map(|(client_id, resources_used)| { + let account_id = *client_id; + let cere_payment: Balance = conv.to_cere(*resources_used as Balance * cluster.cdn_usd_per_gb / KB_PER_GB ); + (account_id, cere_payment) + }).collect::>(); + } + + for &(client_id, payment) in aggregate_payments_accounts.iter() { + if let Ok(mut account) = self.accounts.get(&client_id) { + account.withdraw_bonded(Payable(payment))?; + _undistributed_payment_accounts += payment; + self.accounts.save(&client_id, &account); + } else { + return Err(InsufficientBalance) + } + }; + + let conv = &self.accounts.1; + let committer = &mut self.committer_store; + + for &(cdn_node_key, resources_used) in aggregates_nodes.iter() { + let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; + let protocol_fee = self.protocol_store.get_fee_bp(); + let protocol = &mut self.protocol_store; + + let payment = conv.to_cere (resources_used as Balance * cluster.cdn_usd_per_gb / KB_PER_GB ); + + // let protocol_payment = payment * protocol_fee as u128/ 10_000; + let node_payment = payment * (10_000 - protocol_fee) as u128 / 10_000; + let protocol_payment = payment - node_payment; + + cdn_node.put_payment(node_payment); + + protocol.put_revenues(Cash(protocol_payment)); + self.cdn_nodes.update(cdn_node_key, &cdn_node)?; + + committer.set_validated_commit(cdn_node_key, era).unwrap(); + cluster_payment += node_payment; + } + // Add check that two payments should equal? + + // Go through buckets and deduct used resources + for &(bucket_id, resources_used) in aggregates_buckets.iter() { + let bucket = self.buckets.get_mut(bucket_id)?; + + if bucket.resource_consumption_cap <= resources_used { + bucket.resource_consumption_cap -= resources_used; + } + } + + // Add revenues to cluster + cluster.cdn_put_revenues(Cash(cluster_payment)); + self.clusters.update(cluster_id, &cluster)?; + + Ok(()) + } + + + pub fn message_cdn_cluster_distribute_revenues(&mut self, cluster_id: ClusterId) -> Result<()> { + let mut cluster = self.clusters.get(cluster_id)?; + + // Charge the network fee from the cluster. + Self::capture_network_fee(&self.network_fee, &mut cluster.revenues)?; + + // Charge the cluster management fee. + Self::capture_fee( + self.network_fee.cluster_management_fee_bp(), + cluster.manager_id, + &mut cluster.revenues)?; + + // First accumulated revenues to distribute. + let mut distributed_revenue = 0; + + for cdn_node_key in &cluster.cdn_nodes_keys { + let cdn_node = self.cdn_nodes.get(*cdn_node_key)?; + distributed_revenue += cdn_node.undistributed_payment; + } + + // Charge the provider payments from the cluster. + cluster.revenues.pay(Payable(distributed_revenue))?; + + // Distribute revenues to nodes + for cdn_node_key in &cluster.cdn_nodes_keys { + let mut cdn_node = self.cdn_nodes.get(*cdn_node_key)?; + + Self::send_cash(cdn_node.provider_id, Cash(cdn_node.undistributed_payment))?; + cdn_node.take_payment(cdn_node.undistributed_payment)?; + self.cdn_nodes.update(*cdn_node_key, &cdn_node)?; + + Self::env().emit_event(ClusterDistributeRevenues { + cluster_id, + provider_id: cdn_node.provider_id + }); + } + self.clusters.update(cluster_id, &cluster)?; + + Ok(()) + } + + fn only_cluster_manager(cluster: &Cluster) -> Result { let caller = Self::env().caller(); if caller == cluster.manager_id { @@ -330,6 +480,7 @@ impl DdcBucket { } } + fn only_trusted_manager( perm_store: &PermStore, manager: AccountId, @@ -343,4 +494,6 @@ impl DdcBucket { Err(ClusterManagerIsNotTrusted) } } + + } diff --git a/bucket/ddc_bucket/cluster/store.rs b/bucket/ddc_bucket/cluster/store.rs index 5557c1d0..e9a8c413 100644 --- a/bucket/ddc_bucket/cluster/store.rs +++ b/bucket/ddc_bucket/cluster/store.rs @@ -1,15 +1,11 @@ //! The store where to create and access Clusters by ID. -use ink_prelude::vec::Vec; use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; use ink_storage::Mapping; - -use crate::ddc_bucket::node::entity::{NodeKey}; -use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; use crate::ddc_bucket::{AccountId, Error::*, Result}; - use super::entity::{Cluster, ClusterId, ClusterParams}; + #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(StorageLayout, Debug))] pub struct ClusterStore { diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index c40c5082..0ecd39fc 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -66,7 +66,6 @@ pub struct NodeInfo { impl Node { pub fn new( - node_key: AccountId, provider_id: AccountId, node_params: NodeParams, capacity: Resource, @@ -120,7 +119,7 @@ impl Node { } pub fn only_with_cluster(&self, cluster_id: ClusterId) -> Result<()> { - if let Some(cluster_id) = self.cluster_id { + if let Some(_) = self.cluster_id { Ok(()) } else { Err(NodeIsNotAddedToCluster(cluster_id)) diff --git a/bucket/ddc_bucket/node/store.rs b/bucket/ddc_bucket/node/store.rs index b9f403aa..b510e47a 100644 --- a/bucket/ddc_bucket/node/store.rs +++ b/bucket/ddc_bucket/node/store.rs @@ -7,7 +7,7 @@ use ink_storage::Mapping; // use crate::ddc_bucket::node::entity::Resource; use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; -use super::entity::{Node, NodeStatus, NodeKey, NodeParams, Resource}; +use super::entity::{Node, NodeKey, NodeParams, Resource}; #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(StorageLayout, Debug))] @@ -31,7 +31,6 @@ impl NodeStore { Err(NodeAlreadyExists) } else { let node = Node::new( - node_key, provider_id, node_params, capacity, diff --git a/bucket/lib.rs b/bucket/lib.rs index cb6df34f..ed4b1295 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -23,15 +23,11 @@ pub mod ddc_bucket { use perm::store::*; use topology::store::*; - use crate::ddc_bucket::account::entity::Account; - use crate::ddc_bucket::cdn_cluster::entity::CdnClusterStatus; use crate::ddc_bucket::cdn_node::store::CdnNodeStore; - use crate::ddc_bucket::committer::store::EraConfig; - use crate::ddc_bucket::network_fee::{FeeConfig, NetworkFeeStore}; + use crate::ddc_bucket::network_fee::{NetworkFeeStore}; use crate::ddc_bucket::perm::entity::Permission; use self::buckets_perms::store::BucketsPermsStore; - use self::cdn_cluster::store::CdnClusterStore; use self::cdn_node::entity::{CdnNodeInfo, CdnNodeKey, CdnNodeParams}; use self::protocol::store::ProtocolStore; use self::topology::store::TopologyStore; @@ -41,7 +37,6 @@ pub mod ddc_bucket { pub mod bucket; pub mod buckets_perms; pub mod cash; - pub mod cdn_cluster; pub mod cdn_node; pub mod cluster; pub mod committer; @@ -64,7 +59,6 @@ pub mod ddc_bucket { buckets_perms: BucketsPermsStore, bucket_params: ParamsStore, clusters: ClusterStore, - cdn_clusters: CdnClusterStore, cdn_nodes: CdnNodeStore, nodes: NodeStore, accounts: AccountStore, From 68bdb804fc1024a297840ff205f715f926840231 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 26 Jun 2023 15:30:02 +0200 Subject: [PATCH 19/89] feat(cluster): removing a cluster --- bucket/ddc_bucket/cluster/entity.rs | 10 +++++++++- bucket/ddc_bucket/cluster/messages.rs | 15 +++++++++++++++ bucket/ddc_bucket/topology/store.rs | 21 ++++++++++++++++++++- bucket/lib.rs | 7 ++++--- 4 files changed, 48 insertions(+), 5 deletions(-) diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index cd294a66..d1dae5ea 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -11,7 +11,7 @@ use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; use crate::ddc_bucket::params::store::Params; use crate::ddc_bucket::Error::{UnauthorizedClusterManager, InsufficientBalance}; -use crate::ddc_bucket::{AccountId, Balance, Error::InsufficientResources, Result}; +use crate::ddc_bucket::{AccountId, Balance, Error::InsufficientResources, Result, Error::*}; pub type ClusterId = u32; pub type ClusterParams = Params; @@ -126,4 +126,12 @@ impl Cluster { Ok(()) } + pub fn only_without_nodes(&self) -> Result<()> { + if self.nodes_keys.len() > 0 || self.cdn_nodes_keys.len() > 0 { + Err(ClusterIsNotEmpty) + } else { + Ok(()) + } + } + } diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 0d609f49..a369ee07 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -183,6 +183,21 @@ impl DdcBucket { } + pub fn message_cluster_remove( + &mut self, + cluster_id: ClusterId, + ) -> Result<()> { + let cluster: Cluster = self.clusters.get(cluster_id)?; + cluster.only_without_nodes()?; + Self::only_cluster_manager(&cluster)?; + + self.clusters.remove(cluster_id); + self.topology_store.remove_topology(cluster_id)?; + + Ok(()) + } + + pub fn message_cluster_remove_cdn_node( &mut self, cluster_id: ClusterId, diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index d9320af0..2e78d6be 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -24,7 +24,7 @@ pub struct TopologyStore { impl TopologyStore { pub fn get_vnodes_by_cluster(&self, cluster_id: ClusterId) -> Result> { - self.clusters_map.get(cluster_id).ok_or(NoVNodesInCluster(cluster_id)) + self.clusters_map.get(cluster_id).ok_or(ClusterIsNotInitialized(cluster_id)) } pub fn get_vnodes_by_node(&self, node_key: NodeKey) -> Result> { @@ -154,4 +154,23 @@ impl TopologyStore { } + pub fn remove_topology( + &mut self, + cluster_id: ClusterId, + ) -> Result<()> { + + let all_vnodes: Vec = self.get_vnodes_by_cluster(cluster_id)?; + + for v_node in &all_vnodes { + let node_key = self.get_node_by_vnode(cluster_id, *v_node)?; + self.vnodes_map.remove((cluster_id, v_node)); + self.nodes_map.remove(node_key); + } + + self.clusters_map.remove(cluster_id); + + Ok(()) + } + + } diff --git a/bucket/lib.rs b/bucket/lib.rs index ed4b1295..be69ecf3 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -683,8 +683,8 @@ pub mod ddc_bucket { pub fn cluster_remove( &mut self, cluster_id: ClusterId, - ) { - + ) -> Result<()> { + self.message_cluster_remove(cluster_id) } /// Changes Storage node status. @@ -1739,7 +1739,8 @@ pub mod ddc_bucket { UnauthorizedNodeOwner, UnauthorizedCdnNodeOwner, TopologyAlreadyExists, - NoVNodesInCluster(ClusterId), + ClusterIsNotEmpty, + ClusterIsNotInitialized(ClusterId), VNodeDoesNotExistsInCluster(ClusterId), VNodeInNotAssignedToNode(ClusterId, VNodeToken), VNodeIsAlreadyAssignedToNode(NodeKey), From 703970ed233c5315ebcf3872aaf286ce5faaeb30 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 26 Jun 2023 16:58:35 +0200 Subject: [PATCH 20/89] feat(cluster): setting node status --- bucket/ddc_bucket/cdn_node/entity.rs | 24 +++++-- bucket/ddc_bucket/cluster/messages.rs | 90 ++++++++++++++++++------ bucket/ddc_bucket/node/entity.rs | 33 +++++---- bucket/ddc_bucket/node/messages.rs | 14 +--- bucket/ddc_bucket/tests/test_contract.rs | 26 +++---- bucket/lib.rs | 27 +++++-- scripts/sdk/src/abi/ddc_bucket.json | 8 +-- 7 files changed, 150 insertions(+), 72 deletions(-) diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index f71cfede..d8974e2a 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -3,7 +3,7 @@ use ink_storage::traits::{SpreadAllocate, PackedLayout, SpreadLayout, PackedAllocate}; use scale::{Decode, Encode}; use ink_primitives::Key; -use crate::ddc_bucket::{AccountId, Balance, ClusterId, NodeStatus, Error::*, Result}; +use crate::ddc_bucket::{AccountId, Balance, ClusterId, NodeStatusInCluster, Error::*, Result}; use crate::ddc_bucket::params::store::Params; pub type ProviderId = AccountId; @@ -17,8 +17,8 @@ pub struct CdnNode { pub provider_id: ProviderId, pub undistributed_payment: Balance, pub cdn_node_params: CdnNodeParams, - pub status: NodeStatus, - pub cluster_id: Option + pub cluster_id: Option, + pub status_in_cluster: Option, } // https://use.ink/3.x/ink-vs-solidity#nested-mappings--custom--advanced-structures @@ -47,8 +47,8 @@ impl CdnNode { provider_id, cdn_node_params, undistributed_payment, - status: NodeStatus::CREATED, - cluster_id: None + cluster_id: None, + status_in_cluster: None, } } @@ -64,6 +64,20 @@ impl CdnNode { } } + pub fn set_cluster(&mut self, cluster_id: ClusterId, status: NodeStatusInCluster) { + self.cluster_id = Some(cluster_id); + self.status_in_cluster = Some(status); + } + + pub fn unset_cluster(&mut self) { + self.cluster_id = None; + self.status_in_cluster = None; + } + + pub fn change_status_in_cluster(&mut self, status: NodeStatusInCluster) { + self.status_in_cluster = Some(status); + } + pub fn put_payment(&mut self, amount: Balance) { self.undistributed_payment += amount; } diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index a369ee07..2e9e7763 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -15,7 +15,7 @@ use crate::ddc_bucket::Error::{ClusterManagerIsNotTrusted, UnauthorizedClusterMa use crate::ddc_bucket::{ AccountId, Balance, ClusterCreated, ClusterNodeAdded, ClusterNodeRemoved, ClusterCdnNodeAdded, ClusterCdnNodeRemoved, ClusterDistributeRevenues, ClusterReserveResource, - DdcBucket, Result, Error::* + ClusterRemoved, ClusterNodeStatusSet, ClusterCdnNodeStatusSet, DdcBucket, NodeStatusInCluster, Result, Error::* }; use super::entity::{ClusterId, ClusterParams}; @@ -60,7 +60,7 @@ impl DdcBucket { node.only_without_cluster()?; Self::only_trusted_manager(&self.perms, caller, node.provider_id)?; - node.cluster_id = Some(cluster_id); + node.set_cluster(cluster_id, NodeStatusInCluster::ACTIVE); self.nodes.update(node_key, &node)?; let mut cluster: Cluster = self.clusters.get(cluster_id)?; @@ -92,7 +92,7 @@ impl DdcBucket { node.only_with_cluster(cluster_id)?; Self::only_trusted_manager(&self.perms, caller, node.provider_id)?; - node.cluster_id = None; + node.unset_cluster(); self.nodes.update(node_key, &node)?; let mut cluster: Cluster = self.clusters.get(cluster_id)?; @@ -167,7 +167,7 @@ impl DdcBucket { cdn_node.only_without_cluster()?; Self::only_trusted_manager(&self.perms, manager, cdn_node.provider_id)?; - cdn_node.cluster_id = Some(cluster_id); + cdn_node.set_cluster(cluster_id, NodeStatusInCluster::ACTIVE); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; let mut cluster: Cluster = self.clusters.get(cluster_id)?; @@ -183,21 +183,6 @@ impl DdcBucket { } - pub fn message_cluster_remove( - &mut self, - cluster_id: ClusterId, - ) -> Result<()> { - let cluster: Cluster = self.clusters.get(cluster_id)?; - cluster.only_without_nodes()?; - Self::only_cluster_manager(&cluster)?; - - self.clusters.remove(cluster_id); - self.topology_store.remove_topology(cluster_id)?; - - Ok(()) - } - - pub fn message_cluster_remove_cdn_node( &mut self, cluster_id: ClusterId, @@ -209,7 +194,7 @@ impl DdcBucket { cdn_node.only_with_cluster(cluster_id)?; Self::only_trusted_manager(&self.perms, caller, cdn_node.provider_id)?; - cdn_node.cluster_id = None; + cdn_node.unset_cluster(); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; let mut cluster: Cluster = self.clusters.get(cluster_id)?; @@ -227,6 +212,71 @@ impl DdcBucket { } + pub fn message_cluster_remove( + &mut self, + cluster_id: ClusterId, + ) -> Result<()> { + let cluster: Cluster = self.clusters.get(cluster_id)?; + cluster.only_without_nodes()?; + Self::only_cluster_manager(&cluster)?; + + self.clusters.remove(cluster_id); + self.topology_store.remove_topology(cluster_id)?; + + Self::env().emit_event(ClusterRemoved { + cluster_id, + }); + + Ok(()) + } + + + pub fn message_cluster_set_node_status( + &mut self, + cluster_id: ClusterId, + node_key: NodeKey, + status_in_cluster: NodeStatusInCluster + ) -> Result<()> { + let cluster: Cluster = self.clusters.get(cluster_id)?; + Self::only_cluster_manager(&cluster)?; + + let mut node = self.nodes.get(node_key)?; + node.change_status_in_cluster(status_in_cluster.clone()); + self.nodes.update(node_key, &node)?; + + Self::env().emit_event(ClusterNodeStatusSet { + node_key, + cluster_id, + status: status_in_cluster + }); + + Ok(()) + } + + + pub fn message_cluster_set_cdn_node_status( + &mut self, + cluster_id: ClusterId, + cdn_node_key: CdnNodeKey, + status_in_cluster: NodeStatusInCluster + ) -> Result<()> { + let cluster: Cluster = self.clusters.get(cluster_id)?; + Self::only_cluster_manager(&cluster)?; + + let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; + cdn_node.change_status_in_cluster(status_in_cluster.clone()); + self.cdn_nodes.update(cdn_node_key, &cdn_node)?; + + Self::env().emit_event(ClusterCdnNodeStatusSet { + cdn_node_key, + cluster_id, + status: status_in_cluster + }); + + Ok(()) + } + + pub fn message_cluster_reserve_resource( &mut self, cluster_id: ClusterId, diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index 0ecd39fc..e1ce034d 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -22,8 +22,8 @@ pub struct Node { pub rent_per_month: Balance, pub free_resource: Resource, pub node_params: NodeParams, - pub status: NodeStatus, - pub cluster_id: Option + pub cluster_id: Option, + pub status_in_cluster: Option, } // https://use.ink/3.x/ink-vs-solidity#nested-mappings--custom--advanced-structures @@ -36,23 +36,22 @@ impl ink_storage::traits::PackedAllocate for Node { #[derive(Clone, PartialEq, Encode, Decode, SpreadLayout, PackedLayout)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] -pub enum NodeStatus { - CREATED, +pub enum NodeStatusInCluster { ACTIVE, ADDING, DELETING, OFFLINE, } -impl SpreadAllocate for NodeStatus { +impl SpreadAllocate for NodeStatusInCluster { fn allocate_spread(_: &mut KeyPtr) -> Self { - NodeStatus::CREATED + NodeStatusInCluster::ACTIVE } } -impl Default for NodeStatus { +impl Default for NodeStatusInCluster { fn default() -> Self { - NodeStatus::CREATED + NodeStatusInCluster::ACTIVE } } @@ -76,8 +75,8 @@ impl Node { node_params, free_resource: capacity, rent_per_month, - status: NodeStatus::CREATED, - cluster_id: None + cluster_id: None, + status_in_cluster: None, } } @@ -93,8 +92,18 @@ impl Node { } } - pub fn change_tag(&mut self, new_tag: NodeStatus) { - self.status = new_tag; + pub fn set_cluster(&mut self, cluster_id: ClusterId, status: NodeStatusInCluster) { + self.cluster_id = Some(cluster_id); + self.status_in_cluster = Some(status); + } + + pub fn unset_cluster(&mut self) { + self.cluster_id = None; + self.status_in_cluster = None; + } + + pub fn change_status_in_cluster(&mut self, status: NodeStatusInCluster) { + self.status_in_cluster = Some(status); } pub fn put_resource(&mut self, amount: Resource) { diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index 493e5796..552273ff 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -1,8 +1,9 @@ //! The public interface to manage Nodes. -use crate::ddc_bucket::node::entity::{NodeInfo, Resource, NodeKey, NodeParams, NodeStatus}; +use crate::ddc_bucket::node::entity::{NodeInfo, Resource, NodeKey, NodeParams, NodeStatusInCluster}; use crate::ddc_bucket::perm::entity::Permission; use crate::ddc_bucket::{AccountId, Balance, DdcBucket, NodeCreated, NodeRemoved, NodeParamsSet, Result}; +use crate::ddc_bucket::cluster::entity::ClusterId; use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; @@ -121,16 +122,7 @@ impl DdcBucket { (nodes, self.nodes.keys.len().try_into().unwrap()) } - - pub fn message_node_change_tag(&mut self, node_key: NodeKey, new_tag: NodeStatus) -> Result<()> { - let caller = Self::env().caller(); - let mut node = self.nodes.get(node_key)?; - node.only_owner(caller)?; - node.change_tag(new_tag); - self.nodes.update(node_key, &node)?; - - Ok(()) - } + pub fn message_node_trust_manager( &mut self, diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index 39f93d3f..347f23c1 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -4,7 +4,7 @@ use crate::ddc_bucket::account::entity::Account; // use crate::ddc_bucket::cdn_node::entity::CdnNodeKey; use crate::ddc_bucket::cluster::entity::ClusterInfo; use crate::ddc_bucket::flow::Flow; -use crate::ddc_bucket::node::entity::{NodeStatus, NodeKey}; +use crate::ddc_bucket::node::entity::{NodeStatusInCluster, NodeKey}; use crate::ddc_bucket::schedule::{Schedule, MS_PER_MONTH}; use crate::ddc_bucket::Error::*; use crate::ddc_bucket::*; @@ -71,7 +71,7 @@ fn new_cluster() -> TestCluster { rent_per_vnode, node_params0.to_string(), capacity, - NodeStatus::ADDING, + NodeStatusInCluster::ADDING, ); // Provide another Node. @@ -83,7 +83,7 @@ fn new_cluster() -> TestCluster { rent_per_vnode, node_params1.to_string(), capacity, - NodeStatus::ADDING, + NodeStatusInCluster::ADDING, ); // Provide another Node. @@ -95,7 +95,7 @@ fn new_cluster() -> TestCluster { rent_per_vnode, node_params2.to_string(), capacity, - NodeStatus::ADDING, + NodeStatusInCluster::ADDING, ); // Create a Cluster. @@ -321,7 +321,7 @@ fn cluster_create_works() { provider_id: ctx.provider_id0, rent_per_month: ctx.rent_per_vnode, free_resource: ctx.capacity - ctx.reserved * 3, - status: NodeStatus::ADDING, + status: NodeStatusInCluster::ADDING, node_params: ctx.node_params0.to_string(), } } @@ -336,7 +336,7 @@ fn cluster_create_works() { provider_id: ctx.provider_id1, rent_per_month: ctx.rent_per_vnode, free_resource: ctx.capacity - ctx.reserved * 3, - status: NodeStatus::ADDING, + status: NodeStatusInCluster::ADDING, node_params: ctx.node_params1.to_string(), } } @@ -351,7 +351,7 @@ fn cluster_create_works() { provider_id: ctx.provider_id2, rent_per_month: ctx.rent_per_vnode, free_resource: ctx.capacity - ctx.reserved * 3, - status: NodeStatus::ADDING, + status: NodeStatusInCluster::ADDING, node_params: ctx.node_params2.to_string(), } } @@ -807,7 +807,7 @@ fn cluster_add_node() { let rent_per_month = 100; let node_params = "new_node"; let capacity = 1000; - let status = NodeStatus::ACTIVE; + let status = NodeStatusInCluster::ACTIVE; set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); let new_node_id = ctx.contract.node_create( @@ -994,7 +994,7 @@ fn bucket_reserve_0_works() { provider_id: AccountId::default(), rent_per_month: 0, free_resource: 0, - status: NodeStatus::ACTIVE, + status: NodeStatusInCluster::ACTIVE, node_params: "".to_string(), } }], @@ -1315,7 +1315,7 @@ fn node_list_works() { rent_per_month, node_params1.to_string(), capacity, - NodeStatus::ADDING, + NodeStatusInCluster::ADDING, ); let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; @@ -1325,7 +1325,7 @@ fn node_list_works() { rent_per_month, node_params2.to_string(), capacity, - NodeStatus::ADDING, + NodeStatusInCluster::ADDING, ); let node_status = ddc_bucket.node_get(AccountId::from([0x0b; 32])).unwrap(); @@ -1340,7 +1340,7 @@ fn node_list_works() { provider_id: owner_id1, rent_per_month, free_resource: capacity, - status: NodeStatus::ADDING, + status: NodeStatusInCluster::ADDING, node_params: node_params1.to_string(), }, }; @@ -1351,7 +1351,7 @@ fn node_list_works() { provider_id: owner_id2, rent_per_month, free_resource: capacity, - status: NodeStatus::ADDING, + status: NodeStatusInCluster::ADDING, node_params: node_params2.to_string(), }, }; diff --git a/bucket/lib.rs b/bucket/lib.rs index be69ecf3..e3ff5d3d 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -373,7 +373,9 @@ pub mod ddc_bucket { pub struct ClusterNodeStatusSet { #[ink(topic)] node_key: NodeKey, - status: NodeStatus + #[ink(topic)] + cluster_id: ClusterId, + status: NodeStatusInCluster } #[ink(event)] @@ -381,7 +383,9 @@ pub mod ddc_bucket { pub struct ClusterCdnNodeStatusSet { #[ink(topic)] cdn_node_key: CdnNodeKey, - status: NodeStatus + #[ink(topic)] + cluster_id: ClusterId, + status: NodeStatusInCluster } /// A vnode was re-assigned to new node. @@ -716,9 +720,13 @@ pub mod ddc_bucket { &mut self, cluster_id: ClusterId, node_key: NodeKey, - status: NodeStatus - ) { - self.message_node_change_tag(node_key, status).unwrap(); + status_in_cluster: NodeStatusInCluster + ) -> Result<()> { + self.message_cluster_set_node_status( + cluster_id, + node_key, + status_in_cluster + ) } /// Changes CDN node status. @@ -750,8 +758,13 @@ pub mod ddc_bucket { &mut self, cluster_id: ClusterId, cdn_node_key: CdnNodeKey, - status: NodeStatus - ) { + status_in_cluster: NodeStatusInCluster + ) -> Result<()> { + self.message_cluster_set_cdn_node_status( + cluster_id, + cdn_node_key, + status_in_cluster + ) } /// Gets a cluster. diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index 595bfce2..2d5eff5c 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -1265,7 +1265,7 @@ "label": "new_tag", "type": { "displayName": [ - "NodeStatus" + "NodeStatusInCluster" ], "type": 27 } @@ -2149,7 +2149,7 @@ "label": "status", "type": { "displayName": [ - "NodeStatus" + "NodeStatusInCluster" ], "type": 27 } @@ -3661,7 +3661,7 @@ { "name": "status", "type": 27, - "typeName": "NodeStatus" + "typeName": "NodeStatusInCluster" }, { "name": "node_params", @@ -3714,7 +3714,7 @@ "ddc_bucket", "node", "entity", - "NodeStatus" + "NodeStatusInCluster" ] } }, From fe29173f12e86a42195addcb35d460f932d602f3 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 26 Jun 2023 17:30:44 +0200 Subject: [PATCH 21/89] feat(cluster): granting and revoking manager permissions --- bucket/ddc_bucket/admin.rs | 2 +- bucket/ddc_bucket/cdn_node/messages.rs | 7 -- bucket/ddc_bucket/cluster/messages.rs | 115 +++++++++++++++++-------- bucket/ddc_bucket/node/messages.rs | 11 --- bucket/ddc_bucket/perm/messages.rs | 28 +++--- bucket/lib.rs | 16 ++-- 6 files changed, 104 insertions(+), 75 deletions(-) diff --git a/bucket/ddc_bucket/admin.rs b/bucket/ddc_bucket/admin.rs index c5666b76..d8607ea9 100644 --- a/bucket/ddc_bucket/admin.rs +++ b/bucket/ddc_bucket/admin.rs @@ -11,7 +11,7 @@ impl DdcBucket { is_granted: bool, ) -> Result<()> { self.only_with_permission(Permission::SuperAdmin)?; - self.impl_grant_permission(grantee, permission, is_granted) + self.impl_grant_permission(grantee, permission) } pub fn message_admin_withdraw(&mut self, amount: Balance) -> Result<()> { diff --git a/bucket/ddc_bucket/cdn_node/messages.rs b/bucket/ddc_bucket/cdn_node/messages.rs index 263c367a..7ed86694 100644 --- a/bucket/ddc_bucket/cdn_node/messages.rs +++ b/bucket/ddc_bucket/cdn_node/messages.rs @@ -117,11 +117,4 @@ impl DdcBucket { } - - pub fn message_cdn_node_trust_manager(&mut self, manager: AccountId, is_trusted: bool) -> Result<()> { - let trust_giver = Self::env().caller(); - let permission = Permission::ManagerTrustedBy(trust_giver); - self.impl_grant_permission(manager, permission, is_trusted) - } - } diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 2e9e7763..1c3ac230 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -15,7 +15,7 @@ use crate::ddc_bucket::Error::{ClusterManagerIsNotTrusted, UnauthorizedClusterMa use crate::ddc_bucket::{ AccountId, Balance, ClusterCreated, ClusterNodeAdded, ClusterNodeRemoved, ClusterCdnNodeAdded, ClusterCdnNodeRemoved, ClusterDistributeRevenues, ClusterReserveResource, - ClusterRemoved, ClusterNodeStatusSet, ClusterCdnNodeStatusSet, DdcBucket, NodeStatusInCluster, Result, Error::* + ClusterRemoved, ClusterParamsSet, ClusterNodeStatusSet, ClusterCdnNodeStatusSet, PermissionGranted, PermissionRevoked, DdcBucket, NodeStatusInCluster, Result, Error::* }; use super::entity::{ClusterId, ClusterParams}; @@ -63,7 +63,7 @@ impl DdcBucket { node.set_cluster(cluster_id, NodeStatusInCluster::ACTIVE); self.nodes.update(node_key, &node)?; - let mut cluster: Cluster = self.clusters.get(cluster_id)?; + let mut cluster = self.clusters.get(cluster_id)?; cluster.nodes_keys.push(node_key); for v_node in &v_nodes { cluster.total_rent += node.rent_per_month; @@ -95,7 +95,7 @@ impl DdcBucket { node.unset_cluster(); self.nodes.update(node_key, &node)?; - let mut cluster: Cluster = self.clusters.get(cluster_id)?; + let mut cluster = self.clusters.get(cluster_id)?; if let Some(pos) = cluster.nodes_keys.iter().position(|x| *x == node_key) { cluster.nodes_keys.remove(pos); } @@ -122,8 +122,10 @@ impl DdcBucket { v_nodes: Vec, new_node_key: NodeKey, ) -> Result<()> { + let caller = Self::env().caller(); + let cluster = self.clusters.get(cluster_id)?; - let manager = Self::only_cluster_manager(&cluster)?; + cluster.only_manager(caller)?; // Give back resources to the old node for all its v_nodes for v_node in &v_nodes { @@ -138,7 +140,7 @@ impl DdcBucket { new_node.only_with_cluster(cluster_id)?; // Verify that the provider of the new node trusts the cluster manager. - Self::only_trusted_manager(&self.perms, manager, new_node.provider_id)?; + Self::only_trusted_manager(&self.perms, caller, new_node.provider_id)?; // Reserve resources on the new node. new_node.take_resource(cluster.resource_per_vnode)?; self.nodes.update(new_node_key, &new_node)?; @@ -170,7 +172,7 @@ impl DdcBucket { cdn_node.set_cluster(cluster_id, NodeStatusInCluster::ACTIVE); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; - let mut cluster: Cluster = self.clusters.get(cluster_id)?; + let mut cluster = self.clusters.get(cluster_id)?; cluster.cdn_nodes_keys.push(cdn_node_key); self.clusters.update(cluster_id, &cluster)?; @@ -197,7 +199,7 @@ impl DdcBucket { cdn_node.unset_cluster(); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; - let mut cluster: Cluster = self.clusters.get(cluster_id)?; + let mut cluster = self.clusters.get(cluster_id)?; if let Some(pos) = cluster.cdn_nodes_keys.iter().position(|x| *x == cdn_node_key) { cluster.cdn_nodes_keys.remove(pos); } @@ -216,9 +218,11 @@ impl DdcBucket { &mut self, cluster_id: ClusterId, ) -> Result<()> { - let cluster: Cluster = self.clusters.get(cluster_id)?; + let caller = Self::env().caller(); + + let cluster = self.clusters.get(cluster_id)?; + cluster.only_manager(caller)?; cluster.only_without_nodes()?; - Self::only_cluster_manager(&cluster)?; self.clusters.remove(cluster_id); self.topology_store.remove_topology(cluster_id)?; @@ -237,8 +241,10 @@ impl DdcBucket { node_key: NodeKey, status_in_cluster: NodeStatusInCluster ) -> Result<()> { - let cluster: Cluster = self.clusters.get(cluster_id)?; - Self::only_cluster_manager(&cluster)?; + let caller = Self::env().caller(); + + let cluster = self.clusters.get(cluster_id)?; + cluster.only_manager(caller)?; let mut node = self.nodes.get(node_key)?; node.change_status_in_cluster(status_in_cluster.clone()); @@ -260,8 +266,10 @@ impl DdcBucket { cdn_node_key: CdnNodeKey, status_in_cluster: NodeStatusInCluster ) -> Result<()> { - let cluster: Cluster = self.clusters.get(cluster_id)?; - Self::only_cluster_manager(&cluster)?; + let caller = Self::env().caller(); + + let cluster = self.clusters.get(cluster_id)?; + cluster.only_manager(caller)?; let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; cdn_node.change_status_in_cluster(status_in_cluster.clone()); @@ -277,13 +285,68 @@ impl DdcBucket { } + pub fn message_grant_manager_permission( + &mut self, + manager: AccountId + ) -> Result<()> { + let grantor = Self::env().caller(); + let permission = Permission::ManagerTrustedBy(grantor); + self.impl_grant_permission(manager, permission); + + Self::env().emit_event(PermissionGranted { + account_id: manager, + permission: permission + }); + + Ok(()) + } + + + pub fn message_revoke_manager_permission( + &mut self, + manager: AccountId + ) -> Result<()> { + let grantor = Self::env().caller(); + let permission = Permission::ManagerTrustedBy(grantor); + self.impl_revoke_permission(manager, permission); + + Self::env().emit_event(PermissionRevoked { + account_id: manager, + permission: permission + }); + + Ok(()) + } + + + pub fn message_cluster_set_params( + &mut self, + cluster_id: ClusterId, + cluster_params: ClusterParams, + ) -> Result<()> { + let caller = Self::env().caller(); + let mut cluster = self.clusters.get(cluster_id)?; + cluster.only_manager(caller)?; + cluster.cluster_params = cluster_params.clone(); + self.clusters.update(cluster_id, &cluster)?; + + Self::env().emit_event(ClusterParamsSet { + cluster_id, + params: cluster_params + }); + + Ok(()) + } + + pub fn message_cluster_reserve_resource( &mut self, cluster_id: ClusterId, resource: Resource, ) -> Result<()> { + let caller = Self::env().caller(); let mut cluster = self.clusters.get(cluster_id)?; - Self::only_cluster_manager(&cluster)?; + cluster.only_manager(caller)?; cluster.put_resource(resource); self.clusters.update(cluster_id, &cluster)?; @@ -341,20 +404,6 @@ impl DdcBucket { } - pub fn message_cluster_set_params( - &mut self, - cluster_id: ClusterId, - cluster_params: ClusterParams, - ) -> Result<()> { - let caller = Self::env().caller(); - let mut cluster: Cluster = self.clusters.get(cluster_id)?; - cluster.only_manager(caller)?; - cluster.cluster_params = cluster_params; - self.clusters.update(cluster_id, &cluster)?; - Ok(()) - } - - pub fn message_cluster_get(&self, cluster_id: ClusterId) -> Result { let cluster = self.clusters.get(cluster_id)?.clone(); Ok(ClusterInfo { @@ -534,16 +583,6 @@ impl DdcBucket { Ok(()) } - - - fn only_cluster_manager(cluster: &Cluster) -> Result { - let caller = Self::env().caller(); - if caller == cluster.manager_id { - Ok(caller) - } else { - Err(UnauthorizedClusterManager) - } - } fn only_trusted_manager( diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index 552273ff..a83c4b50 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -122,16 +122,5 @@ impl DdcBucket { (nodes, self.nodes.keys.len().try_into().unwrap()) } - - - pub fn message_node_trust_manager( - &mut self, - manager: AccountId, - is_trusted: bool, - ) -> Result<()> { - let trust_giver = Self::env().caller(); - let permission = Permission::ManagerTrustedBy(trust_giver); - self.impl_grant_permission(manager, permission, is_trusted) - } } \ No newline at end of file diff --git a/bucket/ddc_bucket/perm/messages.rs b/bucket/ddc_bucket/perm/messages.rs index 9df47b04..2b0889e8 100644 --- a/bucket/ddc_bucket/perm/messages.rs +++ b/bucket/ddc_bucket/perm/messages.rs @@ -7,16 +7,23 @@ use crate::ddc_bucket::Error::Unauthorized; use crate::ddc_bucket::perm::entity::Permission; impl DdcBucket { - pub fn impl_grant_permission(&mut self, account_id: AccountId, permission: Permission, is_granted: bool) -> Result<()> { - if is_granted { - self.perms.grant_permission(account_id, &permission); - Self::env().emit_event(PermissionGranted { account_id, permission }); - Ok(()) - } else { - self.perms.revoke_permission(account_id, &permission); - Self::env().emit_event(PermissionRevoked { account_id, permission }); - Ok(()) - } + + pub fn impl_grant_permission(&mut self, account_id: AccountId, permission: Permission) -> Result<()> { + self.perms.grant_permission(account_id, &permission); + Self::env().emit_event(PermissionGranted { + account_id, + permission + }); + Ok(()) + } + + pub fn impl_revoke_permission(&mut self, account_id: AccountId, permission: Permission) -> Result<()> { + self.perms.revoke_permission(account_id, &permission); + Self::env().emit_event(PermissionRevoked { + account_id, + permission + }); + Ok(()) } pub fn only_with_permission(&self, permission: Permission) -> Result { @@ -27,4 +34,5 @@ impl DdcBucket { Err(Unauthorized) } } + } diff --git a/bucket/lib.rs b/bucket/lib.rs index e3ff5d3d..f0e80456 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -1494,7 +1494,7 @@ pub mod ddc_bucket { /// /// # Parameters /// - /// * `cluster_manager` - cluster manager account. + /// * `manager` - cluster manager account. /// /// # Output /// @@ -1510,9 +1510,9 @@ pub mod ddc_bucket { #[ink(message, payable)] pub fn grant_manager_permission( &mut self, - cluster_manager: AccountId - ) { - self.message_node_trust_manager(cluster_manager, true).unwrap(); + manager: AccountId + ) -> Result<()> { + self.message_grant_manager_permission(manager) } /// Revokes permissions from cluster manager. @@ -1523,7 +1523,7 @@ pub mod ddc_bucket { /// /// # Parameters /// - /// * `cluster_manager` - cluster manager account. + /// * `manager` - cluster manager account. /// /// # Output /// @@ -1539,9 +1539,9 @@ pub mod ddc_bucket { #[ink(message)] pub fn revoke_manager_permission( &mut self, - cluster_manager: AccountId - ) { - self.message_node_trust_manager(cluster_manager, false).unwrap(); + manager: AccountId + ) -> Result<()> { + self.message_revoke_manager_permission(manager) } } From 108443a840d5830e8b0c1da4469d2efdd726d702 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 26 Jun 2023 17:49:05 +0200 Subject: [PATCH 22/89] feat(admin): granting and revoking permissions by admin --- bucket/ddc_bucket/admin.rs | 31 ++++++++++- bucket/ddc_bucket/cluster/messages.rs | 80 +++++++++++++-------------- bucket/ddc_bucket/node/messages.rs | 4 +- bucket/lib.rs | 10 ++-- 4 files changed, 73 insertions(+), 52 deletions(-) diff --git a/bucket/ddc_bucket/admin.rs b/bucket/ddc_bucket/admin.rs index d8607ea9..5b360dd5 100644 --- a/bucket/ddc_bucket/admin.rs +++ b/bucket/ddc_bucket/admin.rs @@ -1,21 +1,46 @@ //! The privileged interface for admin tasks. use crate::ddc_bucket::perm::entity::Permission; -use crate::ddc_bucket::{AccountId, Balance, Cash, DdcBucket, Result}; +use crate::ddc_bucket::{AccountId, Balance, Cash, DdcBucket, PermissionGranted, PermissionRevoked, Result}; +use ink_lang::codegen::{EmitEvent, StaticEnv}; impl DdcBucket { + pub fn message_admin_grant_permission( &mut self, grantee: AccountId, permission: Permission, - is_granted: bool, ) -> Result<()> { self.only_with_permission(Permission::SuperAdmin)?; - self.impl_grant_permission(grantee, permission) + self.impl_grant_permission(grantee, permission)?; + + Self::env().emit_event(PermissionGranted { + account_id: grantee, + permission: permission + }); + + Ok(()) + } + + pub fn message_admin_revoke_permission( + &mut self, + grantee: AccountId, + permission: Permission, + ) -> Result<()> { + self.only_with_permission(Permission::SuperAdmin)?; + self.impl_revoke_permission(grantee, permission)?; + + Self::env().emit_event(PermissionRevoked { + account_id: grantee, + permission: permission + }); + + Ok(()) } pub fn message_admin_withdraw(&mut self, amount: Balance) -> Result<()> { let admin = self.only_with_permission(Permission::SuperAdmin)?; Self::send_cash(admin, Cash(amount)) } + } diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 1c3ac230..b21170ea 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -291,7 +291,7 @@ impl DdcBucket { ) -> Result<()> { let grantor = Self::env().caller(); let permission = Permission::ManagerTrustedBy(grantor); - self.impl_grant_permission(manager, permission); + self.impl_grant_permission(manager, permission)?; Self::env().emit_event(PermissionGranted { account_id: manager, @@ -308,7 +308,7 @@ impl DdcBucket { ) -> Result<()> { let grantor = Self::env().caller(); let permission = Permission::ManagerTrustedBy(grantor); - self.impl_revoke_permission(manager, permission); + self.impl_revoke_permission(manager, permission)?; Self::env().emit_event(PermissionRevoked { account_id: manager, @@ -366,44 +366,6 @@ impl DdcBucket { } - pub fn message_cluster_distribute_revenues(&mut self, cluster_id: ClusterId) -> Result<()> { - let mut cluster = self.clusters.get(cluster_id)?; - - // Charge the network fee from the cluster. - Self::capture_network_fee(&self.network_fee, &mut cluster.revenues)?; - - // Charge the cluster management fee. - Self::capture_fee( - self.network_fee.cluster_management_fee_bp(), - cluster.manager_id, - &mut cluster.revenues, - )?; - - // Charge the provider payments from the cluster. - let cluster_vnodes = self.topology_store.get_vnodes_by_cluster(cluster_id)?; - let num_shares = cluster_vnodes.len() as Balance; - let per_share = cluster.revenues.peek() / num_shares; - cluster.revenues.pay(Payable(per_share * num_shares))?; - - for node_key in &cluster.nodes_keys { - let node = self.nodes.get(*node_key)?; - Self::send_cash(node.provider_id, Cash(per_share))?; - - Self::env().emit_event(ClusterDistributeRevenues { - cluster_id, - provider_id: node.provider_id, - }); - } - - self.clusters.update(cluster_id, &cluster)?; - - // TODO: set a maximum node count, or support paging. - // TODO: aggregate the payments per node_id or per provider_id. - - Ok(()) - } - - pub fn message_cluster_get(&self, cluster_id: ClusterId) -> Result { let cluster = self.clusters.get(cluster_id)?.clone(); Ok(ClusterInfo { @@ -442,6 +404,44 @@ impl DdcBucket { } + pub fn message_cluster_distribute_revenues(&mut self, cluster_id: ClusterId) -> Result<()> { + let mut cluster = self.clusters.get(cluster_id)?; + + // Charge the network fee from the cluster. + Self::capture_network_fee(&self.network_fee, &mut cluster.revenues)?; + + // Charge the cluster management fee. + Self::capture_fee( + self.network_fee.cluster_management_fee_bp(), + cluster.manager_id, + &mut cluster.revenues, + )?; + + // Charge the provider payments from the cluster. + let cluster_vnodes = self.topology_store.get_vnodes_by_cluster(cluster_id)?; + let num_shares = cluster_vnodes.len() as Balance; + let per_share = cluster.revenues.peek() / num_shares; + cluster.revenues.pay(Payable(per_share * num_shares))?; + + for node_key in &cluster.nodes_keys { + let node = self.nodes.get(*node_key)?; + Self::send_cash(node.provider_id, Cash(per_share))?; + + Self::env().emit_event(ClusterDistributeRevenues { + cluster_id, + provider_id: node.provider_id, + }); + } + + self.clusters.update(cluster_id, &cluster)?; + + // TODO: set a maximum node count, or support paging. + // TODO: aggregate the payments per node_id or per provider_id. + + Ok(()) + } + + // Set the price usd per gb pub fn message_cdn_set_rate( &mut self, diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index a83c4b50..f217f557 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -1,9 +1,7 @@ //! The public interface to manage Nodes. -use crate::ddc_bucket::node::entity::{NodeInfo, Resource, NodeKey, NodeParams, NodeStatusInCluster}; -use crate::ddc_bucket::perm::entity::Permission; +use crate::ddc_bucket::node::entity::{NodeInfo, Resource, NodeKey, NodeParams}; use crate::ddc_bucket::{AccountId, Balance, DdcBucket, NodeCreated, NodeRemoved, NodeParamsSet, Result}; -use crate::ddc_bucket::cluster::entity::ClusterId; use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; diff --git a/bucket/lib.rs b/bucket/lib.rs index f0e80456..cba2fa2c 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -1591,9 +1591,8 @@ pub mod ddc_bucket { &mut self, grantee: AccountId, permission: Permission - ) { - self.message_admin_grant_permission(grantee, permission, true) - .unwrap(); + ) -> Result<()> { + self.message_admin_grant_permission(grantee, permission) } /// Revokes any permission. @@ -1621,9 +1620,8 @@ pub mod ddc_bucket { &mut self, grantee: AccountId, permission: Permission - ) { - self.message_admin_grant_permission(grantee, permission, false) - .unwrap(); + ) -> Result<()> { + self.message_admin_revoke_permission(grantee, permission) } /// Transfers Storage node ownership. From 22f549d69b5e07bd06d9a9cd415d9c2a7f77f391 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 26 Jun 2023 18:23:15 +0200 Subject: [PATCH 23/89] feat(admin): transferring node ownership from admin account --- bucket/ddc_bucket/admin.rs | 74 ++++++++++++++++++++++++--- bucket/ddc_bucket/cluster/messages.rs | 6 +-- bucket/ddc_bucket/perm/messages.rs | 4 +- bucket/lib.rs | 23 +++++---- 4 files changed, 87 insertions(+), 20 deletions(-) diff --git a/bucket/ddc_bucket/admin.rs b/bucket/ddc_bucket/admin.rs index 5b360dd5..67243605 100644 --- a/bucket/ddc_bucket/admin.rs +++ b/bucket/ddc_bucket/admin.rs @@ -1,18 +1,24 @@ //! The privileged interface for admin tasks. use crate::ddc_bucket::perm::entity::Permission; -use crate::ddc_bucket::{AccountId, Balance, Cash, DdcBucket, PermissionGranted, PermissionRevoked, Result}; +use crate::ddc_bucket::{AccountId, Balance, Cash, DdcBucket, NodeKey, + NodeOwnershipTransferred, CdnNodeOwnershipTransferred, PermissionGranted, PermissionRevoked, Result, + Error::* +}; use ink_lang::codegen::{EmitEvent, StaticEnv}; impl DdcBucket { + pub fn message_admin_grant_permission( &mut self, grantee: AccountId, permission: Permission, ) -> Result<()> { - self.only_with_permission(Permission::SuperAdmin)?; - self.impl_grant_permission(grantee, permission)?; + self.only_with_permission(Permission::SuperAdmin) + .map_err(|_| UnauthorizedSuperAdmin)?; + + self.grant_permission(grantee, permission)?; Self::env().emit_event(PermissionGranted { account_id: grantee, @@ -22,13 +28,16 @@ impl DdcBucket { Ok(()) } + pub fn message_admin_revoke_permission( &mut self, grantee: AccountId, permission: Permission, ) -> Result<()> { - self.only_with_permission(Permission::SuperAdmin)?; - self.impl_revoke_permission(grantee, permission)?; + self.only_with_permission(Permission::SuperAdmin) + .map_err(|_| UnauthorizedSuperAdmin)?; + + self.revoke_permission(grantee, permission)?; Self::env().emit_event(PermissionRevoked { account_id: grantee, @@ -38,8 +47,61 @@ impl DdcBucket { Ok(()) } + + pub fn message_admin_transfer_node_ownership( + &mut self, + node_key: NodeKey, + new_owner: AccountId + ) -> Result<()> { + self.only_with_permission(Permission::SuperAdmin) + .map_err(|_| UnauthorizedSuperAdmin)?; + + let mut node = self.nodes.get(node_key)?; + let caller = Self::env().caller(); + // allow node ownership transfer only if the current owner is the admin + node.only_owner(caller).map_err(|_| NodeOwnerIsNotSuperAdmin)?; + + node.provider_id = new_owner; + self.nodes.update(node_key, &node)?; + + Self::env().emit_event(NodeOwnershipTransferred { + account_id: new_owner, + node_key: node_key + }); + + Ok(()) + } + + + pub fn message_admin_transfer_cdn_node_ownership( + &mut self, + cdn_node_key: NodeKey, + new_owner: AccountId + ) -> Result<()> { + self.only_with_permission(Permission::SuperAdmin) + .map_err(|_| UnauthorizedSuperAdmin)?; + + let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; + let caller = Self::env().caller(); + // allow node ownership transfer only if the current owner is the admin + cdn_node.only_owner(caller).map_err(|_| CdnNodeOwnerIsNotSuperAdmin)?; + + cdn_node.provider_id = new_owner; + self.cdn_nodes.update(cdn_node_key, &cdn_node)?; + + Self::env().emit_event(CdnNodeOwnershipTransferred { + account_id: new_owner, + cdn_node_key: cdn_node_key + }); + + Ok(()) + } + + pub fn message_admin_withdraw(&mut self, amount: Balance) -> Result<()> { - let admin = self.only_with_permission(Permission::SuperAdmin)?; + let admin = self.only_with_permission(Permission::SuperAdmin) + .map_err(|_| UnauthorizedSuperAdmin)?; + Self::send_cash(admin, Cash(amount)) } diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index b21170ea..92a1fa2d 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -88,7 +88,7 @@ impl DdcBucket { ) -> Result<()> { let caller = Self::env().caller(); - let mut node: Node = self.nodes.get(node_key)?; + let mut node = self.nodes.get(node_key)?; node.only_with_cluster(cluster_id)?; Self::only_trusted_manager(&self.perms, caller, node.provider_id)?; @@ -291,7 +291,7 @@ impl DdcBucket { ) -> Result<()> { let grantor = Self::env().caller(); let permission = Permission::ManagerTrustedBy(grantor); - self.impl_grant_permission(manager, permission)?; + self.grant_permission(manager, permission)?; Self::env().emit_event(PermissionGranted { account_id: manager, @@ -308,7 +308,7 @@ impl DdcBucket { ) -> Result<()> { let grantor = Self::env().caller(); let permission = Permission::ManagerTrustedBy(grantor); - self.impl_revoke_permission(manager, permission)?; + self.revoke_permission(manager, permission)?; Self::env().emit_event(PermissionRevoked { account_id: manager, diff --git a/bucket/ddc_bucket/perm/messages.rs b/bucket/ddc_bucket/perm/messages.rs index 2b0889e8..a94da105 100644 --- a/bucket/ddc_bucket/perm/messages.rs +++ b/bucket/ddc_bucket/perm/messages.rs @@ -8,7 +8,7 @@ use crate::ddc_bucket::perm::entity::Permission; impl DdcBucket { - pub fn impl_grant_permission(&mut self, account_id: AccountId, permission: Permission) -> Result<()> { + pub fn grant_permission(&mut self, account_id: AccountId, permission: Permission) -> Result<()> { self.perms.grant_permission(account_id, &permission); Self::env().emit_event(PermissionGranted { account_id, @@ -17,7 +17,7 @@ impl DdcBucket { Ok(()) } - pub fn impl_revoke_permission(&mut self, account_id: AccountId, permission: Permission) -> Result<()> { + pub fn revoke_permission(&mut self, account_id: AccountId, permission: Permission) -> Result<()> { self.perms.revoke_permission(account_id, &permission); Self::env().emit_event(PermissionRevoked { account_id, diff --git a/bucket/lib.rs b/bucket/lib.rs index cba2fa2c..9303fc4f 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -1552,6 +1552,7 @@ pub mod ddc_bucket { pub struct NodeOwnershipTransferred { #[ink(topic)] account_id: AccountId, + #[ink(topic)] node_key: NodeKey, } @@ -1560,6 +1561,7 @@ pub mod ddc_bucket { pub struct CdnNodeOwnershipTransferred { #[ink(topic)] account_id: AccountId, + #[ink(topic)] cdn_node_key: CdnNodeKey, } @@ -1632,7 +1634,7 @@ pub mod ddc_bucket { /// # Parameters /// /// * `node_key` - Public Key associated with the Storage node. - /// * `owner` - Storage node owner + /// * `new_owner` - New Storage node owner /// /// # Output /// @@ -1651,9 +1653,9 @@ pub mod ddc_bucket { pub fn admin_transfer_node_ownership( &mut self, node_key: NodeKey, - owner: AccountId - ) { - + new_owner: AccountId + ) -> Result<()> { + self.message_admin_transfer_node_ownership(node_key, new_owner) } /// Transfers CDN node ownership. @@ -1664,7 +1666,7 @@ pub mod ddc_bucket { /// # Parameters /// /// * `cdn_node_key` - Public Key associated with the CDN node. - /// * `owner` - CDN node owner + /// * `new_owner` - CDN node owner /// /// # Output /// @@ -1683,9 +1685,9 @@ pub mod ddc_bucket { pub fn admin_transfer_cdn_node_ownership( &mut self, cdn_node_key: CdnNodeKey, - owner: AccountId - ) { - + new_owner: AccountId + ) -> Result<()> { + self.message_admin_transfer_cdn_node_ownership(cdn_node_key, new_owner) } // /// As SuperAdmin, withdraw the funds held in custody in this contract. @@ -1749,13 +1751,16 @@ pub mod ddc_bucket { CdnNodeIsAlreadyAddedToCluster(ClusterId), UnauthorizedNodeOwner, UnauthorizedCdnNodeOwner, + UnauthorizedSuperAdmin, TopologyAlreadyExists, ClusterIsNotEmpty, ClusterIsNotInitialized(ClusterId), VNodeDoesNotExistsInCluster(ClusterId), VNodeInNotAssignedToNode(ClusterId, VNodeToken), VNodeIsAlreadyAssignedToNode(NodeKey), - NodeHasNoAssignedVNodes(NodeKey) + NodeHasNoAssignedVNodes(NodeKey), + NodeOwnerIsNotSuperAdmin, + CdnNodeOwnerIsNotSuperAdmin } pub type Result = core::result::Result; From 0300df28a224aaecde1bdb5067cf7a6586395646 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 26 Jun 2023 20:24:22 +0200 Subject: [PATCH 24/89] chore(topology): better naming for storage variables --- bucket/ddc_bucket/cluster/messages.rs | 16 ++--- bucket/ddc_bucket/topology/store.rs | 88 ++++++++++++++------------- bucket/lib.rs | 4 +- 3 files changed, 56 insertions(+), 52 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 92a1fa2d..4b6d5ced 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -99,7 +99,7 @@ impl DdcBucket { if let Some(pos) = cluster.nodes_keys.iter().position(|x| *x == node_key) { cluster.nodes_keys.remove(pos); } - let v_nodes = self.topology_store.get_vnodes_by_node(node_key)?; + let v_nodes = self.topology_store.get_v_nodes_by_node(node_key)?; for v_node in &v_nodes { cluster.total_rent -= node.rent_per_month; } @@ -129,7 +129,7 @@ impl DdcBucket { // Give back resources to the old node for all its v_nodes for v_node in &v_nodes { - let old_node_key = self.topology_store.get_node_by_vnode(cluster_id, *v_node)?; + let old_node_key = self.topology_store.get_node_by_v_node(cluster_id, *v_node)?; // Give back resources to the old node let mut old_node = self.nodes.get(old_node_key)?; @@ -295,7 +295,7 @@ impl DdcBucket { Self::env().emit_event(PermissionGranted { account_id: manager, - permission: permission + permission }); Ok(()) @@ -312,7 +312,7 @@ impl DdcBucket { Self::env().emit_event(PermissionRevoked { account_id: manager, - permission: permission + permission }); Ok(()) @@ -332,7 +332,7 @@ impl DdcBucket { Self::env().emit_event(ClusterParamsSet { cluster_id, - params: cluster_params + cluster_params }); Ok(()) @@ -350,9 +350,9 @@ impl DdcBucket { cluster.put_resource(resource); self.clusters.update(cluster_id, &cluster)?; - let cluster_vnodes = self.topology_store.get_vnodes_by_cluster(cluster_id)?; + let cluster_vnodes = self.topology_store.get_v_nodes_by_cluster(cluster_id)?; for v_node in cluster_vnodes { - let node_key = self.topology_store.get_node_by_vnode(cluster_id, v_node)?; + let node_key = self.topology_store.get_node_by_v_node(cluster_id, v_node)?; let mut node = self.nodes.get(node_key)?; node.take_resource(resource)?; self.nodes.update(node_key, &node)?; @@ -418,7 +418,7 @@ impl DdcBucket { )?; // Charge the provider payments from the cluster. - let cluster_vnodes = self.topology_store.get_vnodes_by_cluster(cluster_id)?; + let cluster_vnodes = self.topology_store.get_v_nodes_by_cluster(cluster_id)?; let num_shares = cluster_vnodes.len() as Balance; let per_share = cluster.revenues.peek() / num_shares; cluster.revenues.pay(Payable(per_share * num_shares))?; diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index 2e78d6be..fe8f6eab 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -13,37 +13,41 @@ pub type ClusterVNode = (ClusterId, VNodeToken); #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(StorageLayout, Debug))] pub struct TopologyStore { - // virtual nodes within a cluster - clusters_map: Mapping>, // virtual nodes assigned to a physical node - nodes_map: Mapping>, + v_nodes_map: Mapping>, // physical node assigned to a virtual node - vnodes_map: Mapping, + nodes_map: Mapping, + // virtual nodes within a cluster assigned to all its physical nodes + cluster_v_nodes_map: Mapping>, } impl TopologyStore { - pub fn get_vnodes_by_cluster(&self, cluster_id: ClusterId) -> Result> { - self.clusters_map.get(cluster_id).ok_or(ClusterIsNotInitialized(cluster_id)) + pub fn get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Result> { + self.cluster_v_nodes_map.get(cluster_id).ok_or(ClusterIsNotCreated(cluster_id)) } - pub fn get_vnodes_by_node(&self, node_key: NodeKey) -> Result> { - self.nodes_map.get(node_key).ok_or(NodeHasNoAssignedVNodes(node_key)) + pub fn get_v_nodes_by_node(&self, node_key: NodeKey) -> Result> { + self.v_nodes_map.get(node_key).ok_or(NodeHasNoAssignedVNodes(node_key)) } - pub fn get_node_by_vnode(&self, cluster_id: ClusterId, v_node: VNodeToken) -> Result { - self.vnodes_map.get((cluster_id, v_node)).ok_or(VNodeInNotAssignedToNode(cluster_id, v_node)) + pub fn get_node_by_v_node(&self, cluster_id: ClusterId, v_node: VNodeToken) -> Result { + self.nodes_map.get((cluster_id, v_node)).ok_or(VNodeInNotAssignedToNode(cluster_id, v_node)) + } + + pub fn v_node_has_node(&self, cluster_id: ClusterId, v_node: VNodeToken) -> bool { + self.nodes_map.contains((cluster_id, v_node)) } pub fn create_topology( &mut self, cluster_id: ClusterId, ) -> Result<()> { - if self.clusters_map.contains(&cluster_id) { + if self.cluster_v_nodes_map.contains(&cluster_id) { Err(TopologyAlreadyExists) } else { - let all_vnodes: Vec = Vec::new(); - self.clusters_map.insert(cluster_id, &all_vnodes); + let cluster_v_nodes: Vec = Vec::new(); + self.cluster_v_nodes_map.insert(cluster_id, &cluster_v_nodes); Ok(()) } } @@ -55,26 +59,26 @@ impl TopologyStore { v_nodes: Vec, ) -> Result<()> { - let mut all_vnodes: Vec = self.get_vnodes_by_cluster(cluster_id)?; + let mut cluster_v_nodes: Vec = self.get_v_nodes_by_cluster(cluster_id)?; for v_node in &v_nodes { // vnode that is being added should not exist in the cluster topology - if let Some(node_key) = self.vnodes_map.get((cluster_id, v_node)) { + if self.v_node_has_node(cluster_id, *v_node) { return Err(VNodeIsAlreadyAssignedToNode(node_key)); } // vnode that is being added should be assigned to the physical node - self.vnodes_map.insert((cluster_id, v_node), &node_key); + self.nodes_map.insert((cluster_id, v_node), &node_key); // vnode that is being added should be added to the cluster topology - all_vnodes.push(*v_node); + cluster_v_nodes.push(*v_node); } - self.clusters_map.insert(cluster_id, &all_vnodes); + self.cluster_v_nodes_map.insert(cluster_id, &cluster_v_nodes); // vnodes that are being added should be assigned to the physical node - self.nodes_map.insert(node_key, &v_nodes); + self.v_nodes_map.insert(node_key, &v_nodes); Ok(()) } @@ -86,29 +90,29 @@ impl TopologyStore { node_key: NodeKey ) -> Result<()> { - let mut all_vnodes: Vec = self.get_vnodes_by_cluster(cluster_id)?; - let v_nodes = self.get_vnodes_by_node(node_key)?; + let mut cluster_v_nodes: Vec = self.get_v_nodes_by_cluster(cluster_id)?; + let v_nodes = self.get_v_nodes_by_node(node_key)?; for v_node in &v_nodes { // vnode that is being removed should exist in the cluster topology - if None == self.vnodes_map.get((cluster_id, *v_node)) { + if !self.v_node_has_node(cluster_id, *v_node) { return Err(VNodeInNotAssignedToNode(cluster_id, *v_node)); } // vnode that is being removed should be unusigned from the physical node - self.vnodes_map.remove((cluster_id, v_node)); + self.nodes_map.remove((cluster_id, v_node)); // vnode that is being removed should be removed from the cluster topology - if let Some(pos) = all_vnodes.iter().position(|x| *x == *v_node) { - all_vnodes.remove(pos); + if let Some(pos) = cluster_v_nodes.iter().position(|x| *x == *v_node) { + cluster_v_nodes.remove(pos); }; } - self.clusters_map.insert(cluster_id, &all_vnodes); + self.cluster_v_nodes_map.insert(cluster_id, &cluster_v_nodes); // vnodes that are being removed should be unusigned from the physical node - self.nodes_map.remove(node_key); + self.v_nodes_map.remove(node_key); Ok(()) @@ -122,33 +126,33 @@ impl TopologyStore { v_nodes_to_reasign: Vec, ) -> Result<()> { - let all_vnodes = self.get_vnodes_by_cluster(cluster_id)?; + let cluster_v_nodes = self.get_v_nodes_by_cluster(cluster_id)?; for v_node in &v_nodes_to_reasign { // vnode that is being reasigned should be in the cluster topology - if None == all_vnodes.iter().position(|x| *x == *v_node) { + if None == cluster_v_nodes.iter().position(|x| *x == *v_node) { return Err(VNodeDoesNotExistsInCluster(cluster_id)); }; // vnode that is being reasigned should be already assigned to a physical node - let old_node_key = self.get_node_by_vnode(cluster_id, *v_node)?; + let old_node_key = self.get_node_by_v_node(cluster_id, *v_node)?; // vnode that is being reasigned should be among other vnodes assigned to the old physical node - let mut old_node_vnodes = self.get_vnodes_by_node(old_node_key)?; + let mut old_node_v_nodes = self.get_v_nodes_by_node(old_node_key)?; // vnode that is being reasigned should be unasigned from the old physical node - if let Some(pos) = old_node_vnodes.iter().position(|x| *x == *v_node) { - old_node_vnodes.remove(pos); + if let Some(pos) = old_node_v_nodes.iter().position(|x| *x == *v_node) { + old_node_v_nodes.remove(pos); }; - self.nodes_map.insert(old_node_key, &old_node_vnodes); + self.v_nodes_map.insert(old_node_key, &old_node_v_nodes); // vnode that is being reasigned should be assined to the new physical node - self.vnodes_map.insert(&(cluster_id, *v_node), &new_node_key); + self.nodes_map.insert(&(cluster_id, *v_node), &new_node_key); } // vnodes that are being reasigned should be among other vnodes assigned to the new physical node - self.nodes_map.insert(new_node_key, &v_nodes_to_reasign); + self.v_nodes_map.insert(new_node_key, &v_nodes_to_reasign); Ok(()) } @@ -159,15 +163,15 @@ impl TopologyStore { cluster_id: ClusterId, ) -> Result<()> { - let all_vnodes: Vec = self.get_vnodes_by_cluster(cluster_id)?; + let cluster_v_nodes: Vec = self.get_v_nodes_by_cluster(cluster_id)?; - for v_node in &all_vnodes { - let node_key = self.get_node_by_vnode(cluster_id, *v_node)?; - self.vnodes_map.remove((cluster_id, v_node)); - self.nodes_map.remove(node_key); + for v_node in &cluster_v_nodes { + let node_key = self.get_node_by_v_node(cluster_id, *v_node)?; + self.nodes_map.remove((cluster_id, v_node)); + self.v_nodes_map.remove(node_key); } - self.clusters_map.remove(cluster_id); + self.cluster_v_nodes_map.remove(cluster_id); Ok(()) } diff --git a/bucket/lib.rs b/bucket/lib.rs index 9303fc4f..9be425ee 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -357,7 +357,7 @@ pub mod ddc_bucket { pub struct ClusterParamsSet { #[ink(topic)] cluster_id: ClusterId, - params: ClusterParams, + cluster_params: ClusterParams, } @@ -1754,7 +1754,7 @@ pub mod ddc_bucket { UnauthorizedSuperAdmin, TopologyAlreadyExists, ClusterIsNotEmpty, - ClusterIsNotInitialized(ClusterId), + ClusterIsNotCreated(ClusterId), VNodeDoesNotExistsInCluster(ClusterId), VNodeInNotAssignedToNode(ClusterId, VNodeToken), VNodeIsAlreadyAssignedToNode(NodeKey), From ac0bafb336758fa2a732e0751c9be2098a8d02ad Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 26 Jun 2023 20:25:54 +0200 Subject: [PATCH 25/89] chore(topology): better naming for topology event --- bucket/ddc_bucket/topology/store.rs | 2 +- bucket/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index fe8f6eab..0bda06a1 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -24,7 +24,7 @@ pub struct TopologyStore { impl TopologyStore { pub fn get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Result> { - self.cluster_v_nodes_map.get(cluster_id).ok_or(ClusterIsNotCreated(cluster_id)) + self.cluster_v_nodes_map.get(cluster_id).ok_or(ClusterTopologyIsNotCreated(cluster_id)) } pub fn get_v_nodes_by_node(&self, node_key: NodeKey) -> Result> { diff --git a/bucket/lib.rs b/bucket/lib.rs index 9be425ee..6f6654af 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -1754,7 +1754,7 @@ pub mod ddc_bucket { UnauthorizedSuperAdmin, TopologyAlreadyExists, ClusterIsNotEmpty, - ClusterIsNotCreated(ClusterId), + ClusterTopologyIsNotCreated(ClusterId), VNodeDoesNotExistsInCluster(ClusterId), VNodeInNotAssignedToNode(ClusterId, VNodeToken), VNodeIsAlreadyAssignedToNode(NodeKey), From 68352158419a08d536d19e5ab971e8ccc50fbaf7 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 26 Jun 2023 20:57:37 +0200 Subject: [PATCH 26/89] chore(perms): checking for trusted manager permissions --- bucket/ddc_bucket/cluster/messages.rs | 37 +++++---------------------- bucket/ddc_bucket/perm/messages.rs | 19 +++++++++----- 2 files changed, 18 insertions(+), 38 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 4b6d5ced..e119e6a4 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -3,15 +3,13 @@ use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; use crate::ddc_bucket::cash::{Cash, Payable}; -use crate::ddc_bucket::cluster::entity::{Cluster, ClusterInfo}; +use crate::ddc_bucket::cluster::entity::{ClusterInfo}; use crate::ddc_bucket::bucket::entity::{BucketId}; use crate::ddc_bucket::node::entity::{Node, NodeKey, Resource}; use crate::ddc_bucket::cdn_node::entity::{CdnNode, CdnNodeKey}; use crate::ddc_bucket::topology::store::{VNodeToken}; use crate::ddc_bucket::perm::entity::Permission; -use crate::ddc_bucket::perm::store::PermStore; use crate::ddc_bucket::ClusterNodeReplaced; -use crate::ddc_bucket::Error::{ClusterManagerIsNotTrusted, UnauthorizedClusterManager}; use crate::ddc_bucket::{ AccountId, Balance, ClusterCreated, ClusterNodeAdded, ClusterNodeRemoved, ClusterCdnNodeAdded, ClusterCdnNodeRemoved, ClusterDistributeRevenues, ClusterReserveResource, @@ -54,11 +52,9 @@ impl DdcBucket { node_key: NodeKey, v_nodes: Vec, ) -> Result<()> { - let caller = Self::env().caller(); - let mut node: Node = self.nodes.get(node_key)?; node.only_without_cluster()?; - Self::only_trusted_manager(&self.perms, caller, node.provider_id)?; + self.only_trusted_manager(node.provider_id)?; node.set_cluster(cluster_id, NodeStatusInCluster::ACTIVE); self.nodes.update(node_key, &node)?; @@ -86,11 +82,9 @@ impl DdcBucket { cluster_id: ClusterId, node_key: NodeKey, ) -> Result<()> { - let caller = Self::env().caller(); - let mut node = self.nodes.get(node_key)?; node.only_with_cluster(cluster_id)?; - Self::only_trusted_manager(&self.perms, caller, node.provider_id)?; + self.only_trusted_manager(node.provider_id)?; node.unset_cluster(); self.nodes.update(node_key, &node)?; @@ -140,7 +134,7 @@ impl DdcBucket { new_node.only_with_cluster(cluster_id)?; // Verify that the provider of the new node trusts the cluster manager. - Self::only_trusted_manager(&self.perms, caller, new_node.provider_id)?; + self.only_trusted_manager(new_node.provider_id)?; // Reserve resources on the new node. new_node.take_resource(cluster.resource_per_vnode)?; self.nodes.update(new_node_key, &new_node)?; @@ -163,11 +157,9 @@ impl DdcBucket { cluster_id: ClusterId, cdn_node_key: CdnNodeKey, ) -> Result<()> { - let manager = Self::env().caller(); - let mut cdn_node: CdnNode = self.cdn_nodes.get(cdn_node_key)?; cdn_node.only_without_cluster()?; - Self::only_trusted_manager(&self.perms, manager, cdn_node.provider_id)?; + self.only_trusted_manager(cdn_node.provider_id)?; cdn_node.set_cluster(cluster_id, NodeStatusInCluster::ACTIVE); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; @@ -190,11 +182,9 @@ impl DdcBucket { cluster_id: ClusterId, cdn_node_key: CdnNodeKey, ) -> Result<()> { - let caller = Self::env().caller(); - let mut cdn_node: CdnNode = self.cdn_nodes.get(cdn_node_key)?; cdn_node.only_with_cluster(cluster_id)?; - Self::only_trusted_manager(&self.perms, caller, cdn_node.provider_id)?; + self.only_trusted_manager(cdn_node.provider_id)?; cdn_node.unset_cluster(); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; @@ -585,19 +575,4 @@ impl DdcBucket { } - fn only_trusted_manager( - perm_store: &PermStore, - manager: AccountId, - trusted_by: AccountId, - ) -> Result<()> { - let perm = Permission::ManagerTrustedBy(trusted_by); - let trusts = perm_store.has_permission(manager, perm); - if trusts { - Ok(()) - } else { - Err(ClusterManagerIsNotTrusted) - } - } - - } diff --git a/bucket/ddc_bucket/perm/messages.rs b/bucket/ddc_bucket/perm/messages.rs index a94da105..76bd34d8 100644 --- a/bucket/ddc_bucket/perm/messages.rs +++ b/bucket/ddc_bucket/perm/messages.rs @@ -2,8 +2,7 @@ use ink_lang::codegen::{EmitEvent, StaticEnv}; -use crate::ddc_bucket::{AccountId, DdcBucket, PermissionGranted, Result, PermissionRevoked}; -use crate::ddc_bucket::Error::Unauthorized; +use crate::ddc_bucket::{AccountId, DdcBucket, PermissionGranted, PermissionRevoked, Result, Error::* }; use crate::ddc_bucket::perm::entity::Permission; impl DdcBucket { @@ -28,11 +27,17 @@ impl DdcBucket { pub fn only_with_permission(&self, permission: Permission) -> Result { let caller = Self::env().caller(); - if self.perms.has_permission(caller, permission) { - Ok(caller) - } else { - Err(Unauthorized) - } + self.perms.has_permission(caller, permission) + .then(|| caller) + .ok_or(Unauthorized) + } + + pub fn only_trusted_manager(&self, provider_id: AccountId) -> Result { + let caller = Self::env().caller(); + let perm = Permission::ManagerTrustedBy(provider_id); + self.perms.has_permission(caller, perm) + .then(|| caller) + .ok_or(ClusterManagerIsNotTrusted) } } From 9d529684650168297c88b6d165365292330e02df Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 26 Jun 2023 21:26:25 +0200 Subject: [PATCH 27/89] chore(perms): guards function syntax enhanced --- bucket/ddc_bucket/admin.rs | 18 ++++++------ bucket/ddc_bucket/cdn_node/entity.rs | 42 ++++++++++++---------------- bucket/ddc_bucket/cluster/entity.rs | 30 ++++++++++---------- bucket/ddc_bucket/node/entity.rs | 41 ++++++++++++--------------- bucket/ddc_bucket/topology/store.rs | 2 +- bucket/lib.rs | 2 +- 6 files changed, 60 insertions(+), 75 deletions(-) diff --git a/bucket/ddc_bucket/admin.rs b/bucket/ddc_bucket/admin.rs index 67243605..86edb4ca 100644 --- a/bucket/ddc_bucket/admin.rs +++ b/bucket/ddc_bucket/admin.rs @@ -22,7 +22,7 @@ impl DdcBucket { Self::env().emit_event(PermissionGranted { account_id: grantee, - permission: permission + permission }); Ok(()) @@ -41,7 +41,7 @@ impl DdcBucket { Self::env().emit_event(PermissionRevoked { account_id: grantee, - permission: permission + permission }); Ok(()) @@ -53,20 +53,19 @@ impl DdcBucket { node_key: NodeKey, new_owner: AccountId ) -> Result<()> { - self.only_with_permission(Permission::SuperAdmin) + let admin = self.only_with_permission(Permission::SuperAdmin) .map_err(|_| UnauthorizedSuperAdmin)?; let mut node = self.nodes.get(node_key)?; - let caller = Self::env().caller(); // allow node ownership transfer only if the current owner is the admin - node.only_owner(caller).map_err(|_| NodeOwnerIsNotSuperAdmin)?; + node.only_owner(admin).map_err(|_| NodeOwnerIsNotSuperAdmin)?; node.provider_id = new_owner; self.nodes.update(node_key, &node)?; Self::env().emit_event(NodeOwnershipTransferred { account_id: new_owner, - node_key: node_key + node_key }); Ok(()) @@ -78,20 +77,19 @@ impl DdcBucket { cdn_node_key: NodeKey, new_owner: AccountId ) -> Result<()> { - self.only_with_permission(Permission::SuperAdmin) + let admin = self.only_with_permission(Permission::SuperAdmin) .map_err(|_| UnauthorizedSuperAdmin)?; let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; - let caller = Self::env().caller(); // allow node ownership transfer only if the current owner is the admin - cdn_node.only_owner(caller).map_err(|_| CdnNodeOwnerIsNotSuperAdmin)?; + cdn_node.only_owner(admin).map_err(|_| CdnNodeOwnerIsNotSuperAdmin)?; cdn_node.provider_id = new_owner; self.cdn_nodes.update(cdn_node_key, &cdn_node)?; Self::env().emit_event(CdnNodeOwnershipTransferred { account_id: new_owner, - cdn_node_key: cdn_node_key + cdn_node_key }); Ok(()) diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index d8974e2a..7b5df7a1 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -52,16 +52,22 @@ impl CdnNode { } } - pub fn cdn_account_id(&self) -> AccountId { - self.provider_id + pub fn only_owner(&self, caller: AccountId) -> Result<()> { + (self.provider_id == caller) + .then(|| ()) + .ok_or(UnauthorizedNodeOwner) } - pub fn only_owner(&self, owner_id: AccountId) -> Result<()> { - if self.provider_id == owner_id { - Ok(()) - } else { - Err(UnauthorizedCdnNodeOwner) - } + pub fn only_without_cluster(&self) -> Result<()> { + self.cluster_id + .map_or(Ok(()), |cluster_id| Err(CdnNodeIsAlreadyAddedToCluster(cluster_id))) + } + + pub fn only_with_cluster(&self, cluster_id: ClusterId) -> Result<()> { + self.cluster_id + .is_some() + .then(|| ()) + .ok_or(CdnNodeIsNotAddedToCluster(cluster_id)) } pub fn set_cluster(&mut self, cluster_id: ClusterId, status: NodeStatusInCluster) { @@ -78,6 +84,10 @@ impl CdnNode { self.status_in_cluster = Some(status); } + pub fn cdn_account_id(&self) -> AccountId { + self.provider_id + } + pub fn put_payment(&mut self, amount: Balance) { self.undistributed_payment += amount; } @@ -90,21 +100,5 @@ impl CdnNode { Err(InsufficientBalance) } } - - pub fn only_without_cluster(&self) -> Result<()> { - if let Some(cluster_id) = self.cluster_id { - Err(CdnNodeIsAlreadyAddedToCluster(cluster_id)) - } else { - Ok(()) - } - } - - pub fn only_with_cluster(&self, cluster_id: ClusterId) -> Result<()> { - if let Some(_) = self.cluster_id { - Ok(()) - } else { - Err(CdnNodeIsNotAddedToCluster(cluster_id)) - } - } } \ No newline at end of file diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index d1dae5ea..42465eb3 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -72,6 +72,20 @@ impl Cluster { } } + pub fn only_manager(&self, caller: AccountId) -> Result<()> { + (self.manager_id == caller) + .then(|| ()) + .ok_or(UnauthorizedClusterManager) + } + + pub fn only_without_nodes(&self) -> Result<()> { + if self.nodes_keys.is_empty() && self.cdn_nodes_keys.is_empty() { + Ok(()) + } else { + Err(ClusterIsNotEmpty) + } + } + pub fn get_rent(&self, resource: Resource) -> Balance { let rent = self.total_rent * resource as Balance; rent @@ -94,14 +108,6 @@ impl Cluster { Ok(()) } - pub fn only_manager(&self, caller: AccountId) -> Result<()> { - if self.manager_id == caller { - Ok(()) - } else { - Err(UnauthorizedClusterManager) - } - } - pub fn cdn_get_revenue_cere(&self) -> Cash { self.cdn_revenues } @@ -126,12 +132,4 @@ impl Cluster { Ok(()) } - pub fn only_without_nodes(&self) -> Result<()> { - if self.nodes_keys.len() > 0 || self.cdn_nodes_keys.len() > 0 { - Err(ClusterIsNotEmpty) - } else { - Ok(()) - } - } - } diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index e1ce034d..19d67f68 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -80,16 +80,22 @@ impl Node { } } - pub fn revenue_account_id(&self) -> AccountId { - self.provider_id + pub fn only_owner(&self, caller: AccountId) -> Result<()> { + (self.provider_id == caller) + .then(|| ()) + .ok_or(UnauthorizedNodeOwner) } - pub fn only_owner(&self, owner_id: AccountId) -> Result<()> { - if self.provider_id == owner_id { - Ok(()) - } else { - Err(UnauthorizedNodeOwner) - } + pub fn only_without_cluster(&self) -> Result<()> { + self.cluster_id + .map_or(Ok(()), |cluster_id| Err(NodeIsAlreadyAddedToCluster(cluster_id))) + } + + pub fn only_with_cluster(&self, cluster_id: ClusterId) -> Result<()> { + self.cluster_id + .is_some() + .then(|| ()) + .ok_or(NodeIsNotAddedToCluster(cluster_id)) } pub fn set_cluster(&mut self, cluster_id: ClusterId, status: NodeStatusInCluster) { @@ -106,6 +112,10 @@ impl Node { self.status_in_cluster = Some(status); } + pub fn revenue_account_id(&self) -> AccountId { + self.provider_id + } + pub fn put_resource(&mut self, amount: Resource) { self.free_resource += amount; } @@ -119,19 +129,4 @@ impl Node { } } - pub fn only_without_cluster(&self) -> Result<()> { - if let Some(cluster_id) = self.cluster_id { - Err(NodeIsAlreadyAddedToCluster(cluster_id)) - } else { - Ok(()) - } - } - - pub fn only_with_cluster(&self, cluster_id: ClusterId) -> Result<()> { - if let Some(_) = self.cluster_id { - Ok(()) - } else { - Err(NodeIsNotAddedToCluster(cluster_id)) - } - } } diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index 0bda06a1..74ffa633 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -24,7 +24,7 @@ pub struct TopologyStore { impl TopologyStore { pub fn get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Result> { - self.cluster_v_nodes_map.get(cluster_id).ok_or(ClusterTopologyIsNotCreated(cluster_id)) + self.cluster_v_nodes_map.get(cluster_id).ok_or(TopologyIsNotCreated(cluster_id)) } pub fn get_v_nodes_by_node(&self, node_key: NodeKey) -> Result> { diff --git a/bucket/lib.rs b/bucket/lib.rs index 6f6654af..55323386 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -1754,7 +1754,7 @@ pub mod ddc_bucket { UnauthorizedSuperAdmin, TopologyAlreadyExists, ClusterIsNotEmpty, - ClusterTopologyIsNotCreated(ClusterId), + TopologyIsNotCreated(ClusterId), VNodeDoesNotExistsInCluster(ClusterId), VNodeInNotAssignedToNode(ClusterId, VNodeToken), VNodeIsAlreadyAssignedToNode(NodeKey), From df70bdf563247f0979401d7342953fcb41ced5de Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 26 Jun 2023 21:55:37 +0200 Subject: [PATCH 28/89] chore(params): parameters bounds validation --- bucket/ddc_bucket/cdn_node/entity.rs | 21 +++++++++++++++++---- bucket/ddc_bucket/cdn_node/messages.rs | 4 +--- bucket/ddc_bucket/cdn_node/store.rs | 2 +- bucket/ddc_bucket/cluster/entity.rs | 22 ++++++++++++++++++---- bucket/ddc_bucket/cluster/messages.rs | 2 +- bucket/ddc_bucket/cluster/store.rs | 2 +- bucket/ddc_bucket/node/entity.rs | 21 +++++++++++++++++---- bucket/ddc_bucket/node/messages.rs | 2 +- bucket/ddc_bucket/node/store.rs | 2 +- 9 files changed, 58 insertions(+), 20 deletions(-) diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index 7b5df7a1..f255a40a 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -36,20 +36,25 @@ pub struct CdnNodeInfo { pub cdn_node: CdnNode, } +pub const CDN_NODE_PARAMS_MAX_LEN: usize = 100_000; + impl CdnNode { pub fn new( provider_id: AccountId, cdn_node_params: CdnNodeParams, undistributed_payment: Balance - ) -> Self { - CdnNode { + ) -> Result { + let mut cdn_node = CdnNode { provider_id, - cdn_node_params, + cdn_node_params: CdnNodeParams::default(), undistributed_payment, cluster_id: None, status_in_cluster: None, - } + }; + + cdn_node.set_params(cdn_node_params)?; + Ok(cdn_node) } pub fn only_owner(&self, caller: AccountId) -> Result<()> { @@ -70,6 +75,14 @@ impl CdnNode { .ok_or(CdnNodeIsNotAddedToCluster(cluster_id)) } + pub fn set_params(&mut self, cdn_node_params: CdnNodeParams) -> Result<()> { + if cdn_node_params.len() > CDN_NODE_PARAMS_MAX_LEN { + return Err(ParamsTooBig); + } + self.cdn_node_params = cdn_node_params; + Ok(()) + } + pub fn set_cluster(&mut self, cluster_id: ClusterId, status: NodeStatusInCluster) { self.cluster_id = Some(cluster_id); self.status_in_cluster = Some(status); diff --git a/bucket/ddc_bucket/cdn_node/messages.rs b/bucket/ddc_bucket/cdn_node/messages.rs index 7ed86694..b6c2b81f 100644 --- a/bucket/ddc_bucket/cdn_node/messages.rs +++ b/bucket/ddc_bucket/cdn_node/messages.rs @@ -3,7 +3,6 @@ use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; use crate::ddc_bucket::{AccountId, DdcBucket, CdnNodeCreated, CdnNodeRemoved, CdnNodeParamsSet, Result, Balance}; -use crate::ddc_bucket::perm::entity::{Permission}; use super::entity::{CdnNodeKey, CdnNodeInfo, CdnNodeParams}; @@ -51,7 +50,6 @@ impl DdcBucket { cdn_node_key, }); - Ok(()) } @@ -65,7 +63,7 @@ impl DdcBucket { let caller = Self::env().caller(); let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; cdn_node.only_owner(caller)?; - cdn_node.cdn_node_params = cdn_node_params.clone(); + cdn_node.set_params(cdn_node_params.clone())?; self.cdn_nodes.update(cdn_node_key, &cdn_node)?; Self::env().emit_event(CdnNodeParamsSet { diff --git a/bucket/ddc_bucket/cdn_node/store.rs b/bucket/ddc_bucket/cdn_node/store.rs index e722265a..d2d5d8f9 100644 --- a/bucket/ddc_bucket/cdn_node/store.rs +++ b/bucket/ddc_bucket/cdn_node/store.rs @@ -32,7 +32,7 @@ impl CdnNodeStore { provider_id, cdn_node_params, undistributed_payment - ); + )?; self.cdn_nodes.insert(&cdn_node_key, &cdn_node); self.keys.push(cdn_node_key); Ok(cdn_node_key) diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 42465eb3..5d46a185 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -51,15 +51,18 @@ pub struct ClusterInfo { pub cluster: Cluster, } +pub const CLUSTER_PARAMS_MAX_LEN: usize = 100_000; + impl Cluster { pub fn new( manager_id: AccountId, cluster_params: ClusterParams, - ) -> Self { - Cluster { + ) -> Result { + + let mut cluster = Cluster { manager_id, - cluster_params, + cluster_params: ClusterParams::default(), nodes_keys: Vec::new(), resource_per_vnode: 0, resource_used: 0, @@ -69,7 +72,10 @@ impl Cluster { cdn_usd_per_gb: 104_857_600, // setting initially to 1 cent per GB cdn_resources_used: 0, cdn_revenues: Cash(0), - } + }; + + cluster.set_params(cluster_params)?; + Ok(cluster) } pub fn only_manager(&self, caller: AccountId) -> Result<()> { @@ -86,6 +92,14 @@ impl Cluster { } } + pub fn set_params(&mut self, cluster_params: ClusterParams) -> Result<()> { + if cluster_params.len() > CLUSTER_PARAMS_MAX_LEN { + return Err(ParamsTooBig); + } + self.cluster_params = cluster_params; + Ok(()) + } + pub fn get_rent(&self, resource: Resource) -> Balance { let rent = self.total_rent * resource as Balance; rent diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index e119e6a4..75e47bb4 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -317,7 +317,7 @@ impl DdcBucket { let caller = Self::env().caller(); let mut cluster = self.clusters.get(cluster_id)?; cluster.only_manager(caller)?; - cluster.cluster_params = cluster_params.clone(); + cluster.set_params(cluster_params.clone())?; self.clusters.update(cluster_id, &cluster)?; Self::env().emit_event(ClusterParamsSet { diff --git a/bucket/ddc_bucket/cluster/store.rs b/bucket/ddc_bucket/cluster/store.rs index e9a8c413..2a942ab7 100644 --- a/bucket/ddc_bucket/cluster/store.rs +++ b/bucket/ddc_bucket/cluster/store.rs @@ -25,7 +25,7 @@ impl ClusterStore { let cluster = Cluster::new( manager_id, cluster_params - ); + )?; self.clusters.insert(&cluster_id, &cluster); Ok(cluster_id) diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index 19d67f68..68b812f8 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -62,6 +62,8 @@ pub struct NodeInfo { pub node: Node, } +pub const NODE_PARAMS_MAX_LEN: usize = 100_000; + impl Node { pub fn new( @@ -69,15 +71,18 @@ impl Node { node_params: NodeParams, capacity: Resource, rent_per_month: Balance, - ) -> Self { - Node { + ) -> Result { + let mut node = Node { provider_id, - node_params, + node_params: NodeParams::default(), free_resource: capacity, rent_per_month, cluster_id: None, status_in_cluster: None, - } + }; + + node.set_params(node_params)?; + Ok(node) } pub fn only_owner(&self, caller: AccountId) -> Result<()> { @@ -98,6 +103,14 @@ impl Node { .ok_or(NodeIsNotAddedToCluster(cluster_id)) } + pub fn set_params(&mut self, node_params: NodeParams) -> Result<()> { + if node_params.len() > NODE_PARAMS_MAX_LEN { + return Err(ParamsTooBig); + } + self.node_params = node_params; + Ok(()) + } + pub fn set_cluster(&mut self, cluster_id: ClusterId, status: NodeStatusInCluster) { self.cluster_id = Some(cluster_id); self.status_in_cluster = Some(status); diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index f217f557..c3657931 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -64,7 +64,7 @@ impl DdcBucket { let caller = Self::env().caller(); let mut node = self.nodes.get(node_key)?; node.only_owner(caller)?; - node.node_params = node_params.clone(); + node.set_params(node_params.clone())?; self.nodes.update(node_key, &node)?; Self::env().emit_event(NodeParamsSet { diff --git a/bucket/ddc_bucket/node/store.rs b/bucket/ddc_bucket/node/store.rs index b510e47a..0769e998 100644 --- a/bucket/ddc_bucket/node/store.rs +++ b/bucket/ddc_bucket/node/store.rs @@ -35,7 +35,7 @@ impl NodeStore { node_params, capacity, rent_per_month - ); + )?; self.nodes.insert(node_key, &node); self.keys.push(node_key); Ok(node_key) From eb7017b638e4b9c42d61a0c45cc458406796bbbf Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 26 Jun 2023 22:04:54 +0200 Subject: [PATCH 29/89] chore(node): renting per month parameter is returned --- bucket/ddc_bucket/cdn_node/messages.rs | 13 ++++++------- bucket/ddc_bucket/node/messages.rs | 15 +++++++-------- bucket/lib.rs | 4 ++-- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/bucket/ddc_bucket/cdn_node/messages.rs b/bucket/ddc_bucket/cdn_node/messages.rs index b6c2b81f..a021c729 100644 --- a/bucket/ddc_bucket/cdn_node/messages.rs +++ b/bucket/ddc_bucket/cdn_node/messages.rs @@ -16,13 +16,12 @@ impl DdcBucket { let caller = Self::env().caller(); let undistributed_payment: Balance = 0; - self.cdn_nodes - .create( - cdn_node_key, - caller, - cdn_node_params.clone(), - undistributed_payment - )?; + self.cdn_nodes.create( + cdn_node_key, + caller, + cdn_node_params.clone(), + undistributed_payment + )?; Self::env().emit_event(CdnNodeCreated { cdn_node_key, diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index c3657931..069e2a49 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -17,14 +17,13 @@ impl DdcBucket { ) -> Result { let caller = Self::env().caller(); - self.nodes - .create( - node_key, - caller, - node_params.clone(), - capacity, - rent_per_month - )?; + self.nodes.create( + node_key, + caller, + node_params.clone(), + capacity, + rent_per_month + )?; Self::env().emit_event(NodeCreated { node_key, diff --git a/bucket/lib.rs b/bucket/lib.rs index 55323386..def661a7 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -1208,6 +1208,7 @@ pub mod ddc_bucket { /// * `node_key` - Public Keys of the Storage node that should be treated as node identifier. /// * `node_params` - [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. /// * `capacity` - Measure used to evaluate physical node hardware resources. + /// * `rent_per_month` - Renting per month. /// /// # Output /// @@ -1227,9 +1228,8 @@ pub mod ddc_bucket { node_key: NodeKey, node_params: NodeParams, capacity: Resource, + rent_per_month: Balance ) -> Result { - // todo: confirm do we need the 'rent_per_month' param - let rent_per_month = Balance::default(); self.message_node_create( node_key, node_params, From 117068ebbdc98e1224395e200a6782020c3eefaf Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 26 Jun 2023 23:07:59 +0200 Subject: [PATCH 30/89] chore(topology): endpoints for getting virtual nodes --- bucket/ddc_bucket/cluster/entity.rs | 5 ++--- bucket/ddc_bucket/cluster/messages.rs | 21 +++++++++++++++++---- bucket/ddc_bucket/node/entity.rs | 4 +++- bucket/ddc_bucket/node/messages.rs | 14 ++++++++++++-- bucket/ddc_bucket/topology/messages.rs | 21 +++++++++++++++++++++ bucket/ddc_bucket/topology/mod.rs | 1 + bucket/lib.rs | 19 +++++++++++++++++++ 7 files changed, 75 insertions(+), 10 deletions(-) create mode 100644 bucket/ddc_bucket/topology/messages.rs diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 5d46a185..6c332645 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -1,6 +1,4 @@ //! The data structure of Clusters. -// use ink_storage::Mapping; -// use ink_prelude::vec::Vec; use ink_prelude::vec::Vec; use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout, PackedAllocate}; use scale::{Decode, Encode}; @@ -11,7 +9,7 @@ use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; use crate::ddc_bucket::params::store::Params; use crate::ddc_bucket::Error::{UnauthorizedClusterManager, InsufficientBalance}; -use crate::ddc_bucket::{AccountId, Balance, Error::InsufficientResources, Result, Error::*}; +use crate::ddc_bucket::{AccountId, Balance, VNodeToken, Result, Error::*}; pub type ClusterId = u32; pub type ClusterParams = Params; @@ -49,6 +47,7 @@ impl ink_storage::traits::PackedAllocate for Cluster { pub struct ClusterInfo { pub cluster_id: ClusterId, pub cluster: Cluster, + pub cluster_v_nodes: Vec, } pub const CLUSTER_PARAMS_MAX_LEN: usize = 100_000; diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 75e47bb4..d14c99a9 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -357,10 +357,16 @@ impl DdcBucket { pub fn message_cluster_get(&self, cluster_id: ClusterId) -> Result { - let cluster = self.clusters.get(cluster_id)?.clone(); + let cluster = self.clusters.get(cluster_id)?; + + let cluster_v_nodes = self.topology_store + .get_v_nodes_by_cluster(cluster_id) + .unwrap_or(Vec::new()); + Ok(ClusterInfo { cluster_id, cluster, + cluster_v_nodes }) } @@ -383,12 +389,19 @@ impl DdcBucket { continue; // Skip non-matches. } } + + let cluster_v_nodes = self.topology_store + .get_v_nodes_by_cluster(cluster_id) + .unwrap_or(Vec::new()); + // Include the complete status of matched items. - let status = ClusterInfo { + let cluster_info = ClusterInfo { cluster_id, - cluster: cluster.clone(), + cluster, + cluster_v_nodes }; - clusters.push(status); + + clusters.push(cluster_info); } (clusters, self.clusters.next_cluster_id - 1) } diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index 68b812f8..dd09d124 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -1,10 +1,11 @@ //! The data structure of Nodes. use ink_storage::traits::{SpreadAllocate, PackedLayout, SpreadLayout, PackedAllocate}; +use ink_prelude::vec::Vec; use scale::{Decode, Encode}; use crate::ddc_bucket::params::store::Params; -use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; +use crate::ddc_bucket::{AccountId, Balance, VNodeToken, Error::*, Result}; use crate::ddc_bucket::cluster::entity::ClusterId; use ink_storage::traits::KeyPtr; @@ -60,6 +61,7 @@ impl Default for NodeStatusInCluster { pub struct NodeInfo { pub node_key: NodeKey, pub node: Node, + pub v_nodes: Vec } pub const NODE_PARAMS_MAX_LEN: usize = 100_000; diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index 069e2a49..7e729de3 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -78,9 +78,14 @@ impl DdcBucket { pub fn message_node_get(&self, node_key: NodeKey) -> Result { let node = self.nodes.get(node_key)?; + let v_nodes = self.topology_store + .get_v_nodes_by_node(node_key) + .unwrap_or(Vec::new()); + Ok(NodeInfo { node_key, node, + v_nodes }) } @@ -107,13 +112,18 @@ impl DdcBucket { } } + let v_nodes = self.topology_store + .get_v_nodes_by_node(node_key) + .unwrap_or(Vec::new()); + // Include the complete status of matched items. - let status = NodeInfo { + let node_info = NodeInfo { node_key, node, + v_nodes }; - nodes.push(status); + nodes.push(node_info); } (nodes, self.nodes.keys.len().try_into().unwrap()) diff --git a/bucket/ddc_bucket/topology/messages.rs b/bucket/ddc_bucket/topology/messages.rs new file mode 100644 index 00000000..39cffd0b --- /dev/null +++ b/bucket/ddc_bucket/topology/messages.rs @@ -0,0 +1,21 @@ +//! The public interface to manage Nodes. + +use crate::ddc_bucket::{NodeKey, ClusterId, VNodeToken, DdcBucket, Result}; +use ink_prelude::vec::Vec; + + +impl DdcBucket { + + pub fn message_get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Result> { + self.topology_store.get_v_nodes_by_cluster(cluster_id) + } + + pub fn message_get_v_nodes_by_node(&self, node_key: NodeKey) -> Result> { + self.topology_store.get_v_nodes_by_node(node_key) + } + + pub fn message_get_node_by_v_node(&self, cluster_id: ClusterId, v_node: VNodeToken) -> Result { + self.topology_store.get_node_by_v_node(cluster_id, v_node) + } + +} \ No newline at end of file diff --git a/bucket/ddc_bucket/topology/mod.rs b/bucket/ddc_bucket/topology/mod.rs index 79be79e2..61483b4e 100644 --- a/bucket/ddc_bucket/topology/mod.rs +++ b/bucket/ddc_bucket/topology/mod.rs @@ -1,3 +1,4 @@ //! cluster topology management. pub mod store; +pub mod messages; diff --git a/bucket/lib.rs b/bucket/lib.rs index def661a7..12570b09 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -1716,6 +1716,25 @@ pub mod ddc_bucket { } // ---- End Accounts ---- + impl DdcBucket { + + #[ink(message)] + pub fn get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Result> { + self.message_get_v_nodes_by_cluster(cluster_id) + } + + #[ink(message)] + pub fn get_v_nodes_by_node(&self, node_key: NodeKey) -> Result> { + self.message_get_v_nodes_by_node(node_key) + } + + #[ink(message)] + pub fn get_node_by_v_node(&self, cluster_id: ClusterId, v_node: VNodeToken) -> Result { + self.message_get_node_by_v_node(cluster_id, v_node) + } + + } + // ---- Utils ---- /// One token with 10 decimals. pub const TOKEN: Balance = 10_000_000_000; From 055f7ee416fbe8c7ec421c627df497e8b8271e23 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 26 Jun 2023 23:34:08 +0200 Subject: [PATCH 31/89] chore(topology): topology store validation is fixed --- bucket/ddc_bucket/cluster/messages.rs | 19 +++++++------------ bucket/ddc_bucket/node/messages.rs | 10 ++-------- bucket/ddc_bucket/topology/messages.rs | 4 ++-- bucket/ddc_bucket/topology/store.rs | 20 ++++++++++---------- bucket/lib.rs | 8 +++++--- 5 files changed, 26 insertions(+), 35 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index d14c99a9..05d93456 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -93,7 +93,7 @@ impl DdcBucket { if let Some(pos) = cluster.nodes_keys.iter().position(|x| *x == node_key) { cluster.nodes_keys.remove(pos); } - let v_nodes = self.topology_store.get_v_nodes_by_node(node_key)?; + let v_nodes = self.topology_store.get_v_nodes_by_node(node_key); for v_node in &v_nodes { cluster.total_rent -= node.rent_per_month; } @@ -340,8 +340,8 @@ impl DdcBucket { cluster.put_resource(resource); self.clusters.update(cluster_id, &cluster)?; - let cluster_vnodes = self.topology_store.get_v_nodes_by_cluster(cluster_id)?; - for v_node in cluster_vnodes { + let cluster_v_nodes = self.topology_store.get_v_nodes_by_cluster(cluster_id); + for v_node in cluster_v_nodes { let node_key = self.topology_store.get_node_by_v_node(cluster_id, v_node)?; let mut node = self.nodes.get(node_key)?; node.take_resource(resource)?; @@ -358,10 +358,7 @@ impl DdcBucket { pub fn message_cluster_get(&self, cluster_id: ClusterId) -> Result { let cluster = self.clusters.get(cluster_id)?; - - let cluster_v_nodes = self.topology_store - .get_v_nodes_by_cluster(cluster_id) - .unwrap_or(Vec::new()); + let cluster_v_nodes = self.topology_store.get_v_nodes_by_cluster(cluster_id); Ok(ClusterInfo { cluster_id, @@ -390,9 +387,7 @@ impl DdcBucket { } } - let cluster_v_nodes = self.topology_store - .get_v_nodes_by_cluster(cluster_id) - .unwrap_or(Vec::new()); + let cluster_v_nodes = self.topology_store.get_v_nodes_by_cluster(cluster_id); // Include the complete status of matched items. let cluster_info = ClusterInfo { @@ -421,8 +416,8 @@ impl DdcBucket { )?; // Charge the provider payments from the cluster. - let cluster_vnodes = self.topology_store.get_v_nodes_by_cluster(cluster_id)?; - let num_shares = cluster_vnodes.len() as Balance; + let cluster_v_nodes = self.topology_store.get_v_nodes_by_cluster(cluster_id); + let num_shares = cluster_v_nodes.len() as Balance; let per_share = cluster.revenues.peek() / num_shares; cluster.revenues.pay(Payable(per_share * num_shares))?; diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index 7e729de3..0ac510ea 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -76,18 +76,14 @@ impl DdcBucket { } pub fn message_node_get(&self, node_key: NodeKey) -> Result { - let node = self.nodes.get(node_key)?; - let v_nodes = self.topology_store - .get_v_nodes_by_node(node_key) - .unwrap_or(Vec::new()); + let v_nodes = self.topology_store.get_v_nodes_by_node(node_key); Ok(NodeInfo { node_key, node, v_nodes }) - } pub fn message_node_list( @@ -112,9 +108,7 @@ impl DdcBucket { } } - let v_nodes = self.topology_store - .get_v_nodes_by_node(node_key) - .unwrap_or(Vec::new()); + let v_nodes = self.topology_store.get_v_nodes_by_node(node_key); // Include the complete status of matched items. let node_info = NodeInfo { diff --git a/bucket/ddc_bucket/topology/messages.rs b/bucket/ddc_bucket/topology/messages.rs index 39cffd0b..9a714a62 100644 --- a/bucket/ddc_bucket/topology/messages.rs +++ b/bucket/ddc_bucket/topology/messages.rs @@ -6,11 +6,11 @@ use ink_prelude::vec::Vec; impl DdcBucket { - pub fn message_get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Result> { + pub fn message_get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Vec { self.topology_store.get_v_nodes_by_cluster(cluster_id) } - pub fn message_get_v_nodes_by_node(&self, node_key: NodeKey) -> Result> { + pub fn message_get_v_nodes_by_node(&self, node_key: NodeKey) -> Vec { self.topology_store.get_v_nodes_by_node(node_key) } diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index 74ffa633..4c26723d 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -23,12 +23,12 @@ pub struct TopologyStore { impl TopologyStore { - pub fn get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Result> { - self.cluster_v_nodes_map.get(cluster_id).ok_or(TopologyIsNotCreated(cluster_id)) + pub fn get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Vec { + self.cluster_v_nodes_map.get(cluster_id).unwrap_or(Vec::new()) } - pub fn get_v_nodes_by_node(&self, node_key: NodeKey) -> Result> { - self.v_nodes_map.get(node_key).ok_or(NodeHasNoAssignedVNodes(node_key)) + pub fn get_v_nodes_by_node(&self, node_key: NodeKey) -> Vec { + self.v_nodes_map.get(node_key).unwrap_or(Vec::new()) } pub fn get_node_by_v_node(&self, cluster_id: ClusterId, v_node: VNodeToken) -> Result { @@ -59,7 +59,7 @@ impl TopologyStore { v_nodes: Vec, ) -> Result<()> { - let mut cluster_v_nodes: Vec = self.get_v_nodes_by_cluster(cluster_id)?; + let mut cluster_v_nodes = self.get_v_nodes_by_cluster(cluster_id); for v_node in &v_nodes { @@ -90,8 +90,8 @@ impl TopologyStore { node_key: NodeKey ) -> Result<()> { - let mut cluster_v_nodes: Vec = self.get_v_nodes_by_cluster(cluster_id)?; - let v_nodes = self.get_v_nodes_by_node(node_key)?; + let mut cluster_v_nodes = self.get_v_nodes_by_cluster(cluster_id); + let v_nodes = self.get_v_nodes_by_node(node_key); for v_node in &v_nodes { @@ -126,7 +126,7 @@ impl TopologyStore { v_nodes_to_reasign: Vec, ) -> Result<()> { - let cluster_v_nodes = self.get_v_nodes_by_cluster(cluster_id)?; + let cluster_v_nodes = self.get_v_nodes_by_cluster(cluster_id); for v_node in &v_nodes_to_reasign { @@ -139,7 +139,7 @@ impl TopologyStore { let old_node_key = self.get_node_by_v_node(cluster_id, *v_node)?; // vnode that is being reasigned should be among other vnodes assigned to the old physical node - let mut old_node_v_nodes = self.get_v_nodes_by_node(old_node_key)?; + let mut old_node_v_nodes = self.get_v_nodes_by_node(old_node_key); // vnode that is being reasigned should be unasigned from the old physical node if let Some(pos) = old_node_v_nodes.iter().position(|x| *x == *v_node) { @@ -163,7 +163,7 @@ impl TopologyStore { cluster_id: ClusterId, ) -> Result<()> { - let cluster_v_nodes: Vec = self.get_v_nodes_by_cluster(cluster_id)?; + let cluster_v_nodes: Vec = self.get_v_nodes_by_cluster(cluster_id); for v_node in &cluster_v_nodes { let node_key = self.get_node_by_v_node(cluster_id, *v_node)?; diff --git a/bucket/lib.rs b/bucket/lib.rs index 12570b09..5c88d708 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -1716,15 +1716,16 @@ pub mod ddc_bucket { } // ---- End Accounts ---- + // ---- Topology ---- impl DdcBucket { #[ink(message)] - pub fn get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Result> { + pub fn get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Vec { self.message_get_v_nodes_by_cluster(cluster_id) } #[ink(message)] - pub fn get_v_nodes_by_node(&self, node_key: NodeKey) -> Result> { + pub fn get_v_nodes_by_node(&self, node_key: NodeKey) -> Vec { self.message_get_v_nodes_by_node(node_key) } @@ -1732,8 +1733,9 @@ pub mod ddc_bucket { pub fn get_node_by_v_node(&self, cluster_id: ClusterId, v_node: VNodeToken) -> Result { self.message_get_node_by_v_node(cluster_id, v_node) } - + } + // ---- End Topology ---- // ---- Utils ---- /// One token with 10 decimals. From 19fb5fe142d640a90416fa9ddeba9236f7e593de Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Tue, 27 Jun 2023 00:19:25 +0200 Subject: [PATCH 32/89] chore(cluster): encapsulation for adding/removing nodes --- bucket/ddc_bucket/cluster/entity.rs | 20 ++++++++++++++++++++ bucket/ddc_bucket/cluster/messages.rs | 12 ++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 6c332645..1ede4dd1 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -91,6 +91,26 @@ impl Cluster { } } + pub fn add_node(&mut self, node_key: NodeKey) { + self.nodes_keys.push(node_key); + } + + pub fn remove_node(&mut self, node_key: NodeKey) { + if let Some(pos) = self.nodes_keys.iter().position(|x| *x == node_key) { + self.nodes_keys.remove(pos); + } + } + + pub fn add_cdn_node(&mut self, cdn_node_key: CdnNodeKey) { + self.cdn_nodes_keys.push(cdn_node_key); + } + + pub fn remove_cdn_node(&mut self, cdn_node_key: CdnNodeKey) { + if let Some(pos) = self.cdn_nodes_keys.iter().position(|x| *x == cdn_node_key) { + self.cdn_nodes_keys.remove(pos); + } + } + pub fn set_params(&mut self, cluster_params: ClusterParams) -> Result<()> { if cluster_params.len() > CLUSTER_PARAMS_MAX_LEN { return Err(ParamsTooBig); diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 05d93456..ece0c741 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -60,7 +60,7 @@ impl DdcBucket { self.nodes.update(node_key, &node)?; let mut cluster = self.clusters.get(cluster_id)?; - cluster.nodes_keys.push(node_key); + cluster.add_node(node_key); for v_node in &v_nodes { cluster.total_rent += node.rent_per_month; } @@ -90,9 +90,7 @@ impl DdcBucket { self.nodes.update(node_key, &node)?; let mut cluster = self.clusters.get(cluster_id)?; - if let Some(pos) = cluster.nodes_keys.iter().position(|x| *x == node_key) { - cluster.nodes_keys.remove(pos); - } + cluster.remove_node(node_key); let v_nodes = self.topology_store.get_v_nodes_by_node(node_key); for v_node in &v_nodes { cluster.total_rent -= node.rent_per_month; @@ -165,7 +163,7 @@ impl DdcBucket { self.cdn_nodes.update(cdn_node_key, &cdn_node)?; let mut cluster = self.clusters.get(cluster_id)?; - cluster.cdn_nodes_keys.push(cdn_node_key); + cluster.add_cdn_node(cdn_node_key); self.clusters.update(cluster_id, &cluster)?; Self::env().emit_event(ClusterCdnNodeAdded { @@ -190,9 +188,7 @@ impl DdcBucket { self.cdn_nodes.update(cdn_node_key, &cdn_node)?; let mut cluster = self.clusters.get(cluster_id)?; - if let Some(pos) = cluster.cdn_nodes_keys.iter().position(|x| *x == cdn_node_key) { - cluster.cdn_nodes_keys.remove(pos); - } + cluster.remove_cdn_node(cdn_node_key); self.clusters.update(cluster_id, &cluster)?; Self::env().emit_event(ClusterCdnNodeRemoved { From fdd2ed11b03f8b654c324d5ccc5c60b24796086b Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Tue, 27 Jun 2023 15:07:35 +0200 Subject: [PATCH 33/89] chore(cluster): permissions for removing nodes from a cluster --- bucket/ddc_bucket/admin.rs | 10 ++-- bucket/ddc_bucket/bucket/messages.rs | 2 +- bucket/ddc_bucket/cdn_node/entity.rs | 4 +- bucket/ddc_bucket/cluster/entity.rs | 8 ++-- bucket/ddc_bucket/cluster/messages.rs | 58 ++++++++++++++++++------ bucket/ddc_bucket/node/entity.rs | 4 +- bucket/ddc_bucket/params/store.rs | 7 ++- bucket/ddc_bucket/perm/messages.rs | 2 +- bucket/ddc_bucket/tests/test_contract.rs | 6 +-- bucket/lib.rs | 58 +++++++++++------------- scripts/sdk/src/abi/ddc_bucket.json | 4 +- 11 files changed, 93 insertions(+), 70 deletions(-) diff --git a/bucket/ddc_bucket/admin.rs b/bucket/ddc_bucket/admin.rs index 86edb4ca..a40aee0c 100644 --- a/bucket/ddc_bucket/admin.rs +++ b/bucket/ddc_bucket/admin.rs @@ -16,7 +16,7 @@ impl DdcBucket { permission: Permission, ) -> Result<()> { self.only_with_permission(Permission::SuperAdmin) - .map_err(|_| UnauthorizedSuperAdmin)?; + .map_err(|_| OnlySuperAdmin)?; self.grant_permission(grantee, permission)?; @@ -35,7 +35,7 @@ impl DdcBucket { permission: Permission, ) -> Result<()> { self.only_with_permission(Permission::SuperAdmin) - .map_err(|_| UnauthorizedSuperAdmin)?; + .map_err(|_| OnlySuperAdmin)?; self.revoke_permission(grantee, permission)?; @@ -54,7 +54,7 @@ impl DdcBucket { new_owner: AccountId ) -> Result<()> { let admin = self.only_with_permission(Permission::SuperAdmin) - .map_err(|_| UnauthorizedSuperAdmin)?; + .map_err(|_| OnlySuperAdmin)?; let mut node = self.nodes.get(node_key)?; // allow node ownership transfer only if the current owner is the admin @@ -78,7 +78,7 @@ impl DdcBucket { new_owner: AccountId ) -> Result<()> { let admin = self.only_with_permission(Permission::SuperAdmin) - .map_err(|_| UnauthorizedSuperAdmin)?; + .map_err(|_| OnlySuperAdmin)?; let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; // allow node ownership transfer only if the current owner is the admin @@ -98,7 +98,7 @@ impl DdcBucket { pub fn message_admin_withdraw(&mut self, amount: Balance) -> Result<()> { let admin = self.only_with_permission(Permission::SuperAdmin) - .map_err(|_| UnauthorizedSuperAdmin)?; + .map_err(|_| OnlySuperAdmin)?; Self::send_cash(admin, Cash(amount)) } diff --git a/bucket/ddc_bucket/bucket/messages.rs b/bucket/ddc_bucket/bucket/messages.rs index 55a47a77..fe191953 100644 --- a/bucket/ddc_bucket/bucket/messages.rs +++ b/bucket/ddc_bucket/bucket/messages.rs @@ -183,7 +183,7 @@ impl DdcBucket { fn only_owner_or_cluster_manager(bucket: &Bucket, cluster: &Cluster) -> Result<()> { let caller = Self::env().caller(); - cluster.only_manager(caller) + cluster.only_owner(caller) .or_else(|_| bucket.only_owner(caller)) } diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index f255a40a..a14124da 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -60,7 +60,7 @@ impl CdnNode { pub fn only_owner(&self, caller: AccountId) -> Result<()> { (self.provider_id == caller) .then(|| ()) - .ok_or(UnauthorizedNodeOwner) + .ok_or(OnlyCdnNodeOwner) } pub fn only_without_cluster(&self) -> Result<()> { @@ -77,7 +77,7 @@ impl CdnNode { pub fn set_params(&mut self, cdn_node_params: CdnNodeParams) -> Result<()> { if cdn_node_params.len() > CDN_NODE_PARAMS_MAX_LEN { - return Err(ParamsTooBig); + return Err(ParamsSizeExceedsLimit); } self.cdn_node_params = cdn_node_params; Ok(()) diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 1ede4dd1..7952cc3e 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -8,7 +8,7 @@ use crate::ddc_bucket::node::entity::{Resource, NodeKey}; use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; use crate::ddc_bucket::params::store::Params; -use crate::ddc_bucket::Error::{UnauthorizedClusterManager, InsufficientBalance}; +use crate::ddc_bucket::Error::{OnlyClusterOwner, InsufficientBalance}; use crate::ddc_bucket::{AccountId, Balance, VNodeToken, Result, Error::*}; pub type ClusterId = u32; @@ -77,10 +77,10 @@ impl Cluster { Ok(cluster) } - pub fn only_manager(&self, caller: AccountId) -> Result<()> { + pub fn only_owner(&self, caller: AccountId) -> Result<()> { (self.manager_id == caller) .then(|| ()) - .ok_or(UnauthorizedClusterManager) + .ok_or(OnlyClusterOwner) } pub fn only_without_nodes(&self) -> Result<()> { @@ -113,7 +113,7 @@ impl Cluster { pub fn set_params(&mut self, cluster_params: ClusterParams) -> Result<()> { if cluster_params.len() > CLUSTER_PARAMS_MAX_LEN { - return Err(ParamsTooBig); + return Err(ParamsSizeExceedsLimit); } self.cluster_params = cluster_params; Ok(()) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index ece0c741..01c36414 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -52,6 +52,7 @@ impl DdcBucket { node_key: NodeKey, v_nodes: Vec, ) -> Result<()> { + let mut node: Node = self.nodes.get(node_key)?; node.only_without_cluster()?; self.only_trusted_manager(node.provider_id)?; @@ -82,14 +83,22 @@ impl DdcBucket { cluster_id: ClusterId, node_key: NodeKey, ) -> Result<()> { + let caller = Self::env().caller(); + let mut node = self.nodes.get(node_key)?; + let mut cluster = self.clusters.get(cluster_id)?; + node.only_with_cluster(cluster_id)?; - self.only_trusted_manager(node.provider_id)?; + + if !self.only_trusted_manager(node.provider_id).is_ok() + && !cluster.only_owner(caller).is_ok() + && !node.only_owner(caller).is_ok() { + return Err(OnlyTrustedManagerOrClusterOwnerOrNodeOwner); + } node.unset_cluster(); self.nodes.update(node_key, &node)?; - let mut cluster = self.clusters.get(cluster_id)?; cluster.remove_node(node_key); let v_nodes = self.topology_store.get_v_nodes_by_node(node_key); for v_node in &v_nodes { @@ -117,7 +126,6 @@ impl DdcBucket { let caller = Self::env().caller(); let cluster = self.clusters.get(cluster_id)?; - cluster.only_manager(caller)?; // Give back resources to the old node for all its v_nodes for v_node in &v_nodes { @@ -130,9 +138,13 @@ impl DdcBucket { let mut new_node = self.nodes.get(new_node_key)?; new_node.only_with_cluster(cluster_id)?; + + // Verify that the provider of the new node trusts the cluster manager + if !self.only_trusted_manager(new_node.provider_id).is_ok() + && !cluster.only_owner(caller).is_ok() { + return Err(OnlyTrustedManagerOrClusterOwner); + } - // Verify that the provider of the new node trusts the cluster manager. - self.only_trusted_manager(new_node.provider_id)?; // Reserve resources on the new node. new_node.take_resource(cluster.resource_per_vnode)?; self.nodes.update(new_node_key, &new_node)?; @@ -180,14 +192,22 @@ impl DdcBucket { cluster_id: ClusterId, cdn_node_key: CdnNodeKey, ) -> Result<()> { + let caller = Self::env().caller(); + let mut cdn_node: CdnNode = self.cdn_nodes.get(cdn_node_key)?; + let mut cluster = self.clusters.get(cluster_id)?; + cdn_node.only_with_cluster(cluster_id)?; - self.only_trusted_manager(cdn_node.provider_id)?; + + if !self.only_trusted_manager(cdn_node.provider_id).is_ok() + && !cluster.only_owner(caller).is_ok() + && !cdn_node.only_owner(caller).is_ok() { + return Err(OnlyTrustedManagerOrClusterOwnerOrCdnNodeOwner); + } cdn_node.unset_cluster(); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; - let mut cluster = self.clusters.get(cluster_id)?; cluster.remove_cdn_node(cdn_node_key); self.clusters.update(cluster_id, &cluster)?; @@ -207,7 +227,7 @@ impl DdcBucket { let caller = Self::env().caller(); let cluster = self.clusters.get(cluster_id)?; - cluster.only_manager(caller)?; + cluster.only_owner(caller)?; cluster.only_without_nodes()?; self.clusters.remove(cluster_id); @@ -229,10 +249,14 @@ impl DdcBucket { ) -> Result<()> { let caller = Self::env().caller(); + let mut node = self.nodes.get(node_key)?; let cluster = self.clusters.get(cluster_id)?; - cluster.only_manager(caller)?; - let mut node = self.nodes.get(node_key)?; + if !self.only_trusted_manager(node.provider_id).is_ok() + && !cluster.only_owner(caller).is_ok() { + return Err(OnlyTrustedManagerOrClusterOwner) + } + node.change_status_in_cluster(status_in_cluster.clone()); self.nodes.update(node_key, &node)?; @@ -254,10 +278,14 @@ impl DdcBucket { ) -> Result<()> { let caller = Self::env().caller(); + let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; let cluster = self.clusters.get(cluster_id)?; - cluster.only_manager(caller)?; - let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; + if !self.only_trusted_manager(cdn_node.provider_id).is_ok() + && !cluster.only_owner(caller).is_ok() { + return Err(OnlyTrustedManagerOrClusterOwner) + } + cdn_node.change_status_in_cluster(status_in_cluster.clone()); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; @@ -312,7 +340,7 @@ impl DdcBucket { ) -> Result<()> { let caller = Self::env().caller(); let mut cluster = self.clusters.get(cluster_id)?; - cluster.only_manager(caller)?; + cluster.only_owner(caller)?; cluster.set_params(cluster_params.clone())?; self.clusters.update(cluster_id, &cluster)?; @@ -332,7 +360,7 @@ impl DdcBucket { ) -> Result<()> { let caller = Self::env().caller(); let mut cluster = self.clusters.get(cluster_id)?; - cluster.only_manager(caller)?; + cluster.only_owner(caller)?; cluster.put_resource(resource); self.clusters.update(cluster_id, &cluster)?; @@ -445,7 +473,7 @@ impl DdcBucket { let caller = Self::env().caller(); let mut cluster = self.clusters.get(cluster_id)?; - cluster.only_manager(caller)?; + cluster.only_owner(caller)?; cluster.cdn_set_rate(cdn_usd_per_gb); self.clusters.update(cluster_id, &cluster)?; diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index dd09d124..969b8521 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -90,7 +90,7 @@ impl Node { pub fn only_owner(&self, caller: AccountId) -> Result<()> { (self.provider_id == caller) .then(|| ()) - .ok_or(UnauthorizedNodeOwner) + .ok_or(OnlyNodeOwner) } pub fn only_without_cluster(&self) -> Result<()> { @@ -107,7 +107,7 @@ impl Node { pub fn set_params(&mut self, node_params: NodeParams) -> Result<()> { if node_params.len() > NODE_PARAMS_MAX_LEN { - return Err(ParamsTooBig); + return Err(ParamsSizeExceedsLimit); } self.node_params = node_params; Ok(()) diff --git a/bucket/ddc_bucket/params/store.rs b/bucket/ddc_bucket/params/store.rs index 13933bc6..ffe9a314 100644 --- a/bucket/ddc_bucket/params/store.rs +++ b/bucket/ddc_bucket/params/store.rs @@ -4,8 +4,7 @@ use ink_prelude::string::String; use ink_prelude::vec::Vec; use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; -use crate::ddc_bucket::{Error::ParamsDoesNotExist, Result}; -use crate::ddc_bucket::Error::ParamsTooBig; +use crate::ddc_bucket::{Error::*, Result}; pub type ParamsId = u32; pub type Params = String; @@ -19,7 +18,7 @@ pub struct ParamsStore(pub Vec); impl ParamsStore { pub fn create(&mut self, params: Params) -> Result { if params.len() > PARAMS_MAX_LEN { - return Err(ParamsTooBig); + return Err(ParamsSizeExceedsLimit); } let params_id: ParamsId = self.0.len().try_into().unwrap(); self.0.push(params); @@ -30,7 +29,7 @@ impl ParamsStore { let current = self.0.get_mut(params_id as usize).ok_or(ParamsDoesNotExist)?; if params.len() > PARAMS_MAX_LEN { - return Err(ParamsTooBig); + return Err(ParamsSizeExceedsLimit); } let record_size = if params.len() > current.len() { params.len() - current.len() diff --git a/bucket/ddc_bucket/perm/messages.rs b/bucket/ddc_bucket/perm/messages.rs index 76bd34d8..1485fd02 100644 --- a/bucket/ddc_bucket/perm/messages.rs +++ b/bucket/ddc_bucket/perm/messages.rs @@ -37,7 +37,7 @@ impl DdcBucket { let perm = Permission::ManagerTrustedBy(provider_id); self.perms.has_permission(caller, perm) .then(|| caller) - .ok_or(ClusterManagerIsNotTrusted) + .ok_or(OnlyTrustedManager) } } diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index 347f23c1..f06de155 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -431,7 +431,7 @@ fn cluster_replace_node_only_manager() { vec![1, 2, 3], ctx.node_key2 ), - Err(UnauthorizedClusterManager) + Err(OnlyTrustedManagerOrClusterOwner) ); } @@ -453,7 +453,7 @@ fn cluster_replace_node_only_trusted_manager() { vec![1, 2, 3], ctx.node_key2 ), - Err(ClusterManagerIsNotTrusted) + Err(OnlyTrustedManager) ); } @@ -551,7 +551,7 @@ fn cluster_management_validation_works() { vec![1, 2, 3], AccountId::from([0x0a; 32]) ), - Err(UnauthorizedClusterManager), + Err(OnlyTrustedManagerOrClusterOwner), "only the manager can modify the cluster" ); diff --git a/bucket/lib.rs b/bucket/lib.rs index 5c88d708..6a38b231 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -470,8 +470,7 @@ pub mod ddc_bucket { /// # Errors /// /// * `ClusterDoesNotExist` error if the cluster does not exist. - /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. - /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// * `OnlyTrustedManager` error if the caller is not a trusted manager. /// * `NodeDoesNotExist` error if the adding Storage node does not exist. /// * `NodeIsAlreadyAddedToCluster(ClusterId)` error if the adding Storage node is already added to this or another cluster. #[ink(message, payable)] @@ -505,8 +504,7 @@ pub mod ddc_bucket { /// # Errors /// /// * `ClusterDoesNotExist` error if the cluster does not exist. - /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. - /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// * `OnlyTrustedManagerOrClusterOwnerOrNodeOwner` error if the caller is not a trusted manager, cluster owner or node owner. /// * `NodeDoesNotExist` error if the removing Storage node does not exist. /// * `NodeIsNotAddedToCluster(ClusterId)` error if the removing Storage node is not in this cluster. #[ink(message)] @@ -541,8 +539,7 @@ pub mod ddc_bucket { /// # Errors /// /// * `ClusterDoesNotExist` error if the cluster does not exist. - /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. - /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// * `OnlyTrustedManagerOrClusterOwner` error if the caller is not a trusted manager or cluster owner. /// * `NodeDoesNotExist` error if the new Storage node does not exist. /// * `NodeIsNotAddedToCluster(ClusterId)` error if the new Storage node is not added to this cluster. /// * `NodeIsAlreadyAddedToCluster(ClusterId)` error if the new Storage node is in another cluster. @@ -582,9 +579,8 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. - /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// * `OnlyTrustedManager` error if the caller is not a trusted manager. /// * `CdnNodeDoesNotExist` error if the adding CDN node does not exist. /// * `CdnNodeIsAlreadyAddedToCluster(ClusterId)` error if the adding CDN node is already added to this or another cluster. #[ink(message, payable)] @@ -616,9 +612,8 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. - /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. + /// * `OnlyTrustedManagerOrClusterOwnerOrCdnNodeOwner` error if the caller is not a trusted manager, cluster owner or node owner. /// * `CdnNodeDoesNotExist` error if the removing CDN node does not exist. /// * `CdnNodeIsNotAddedToCluster(ClusterId)` error if the removing CDN node is not in this cluster. #[ink(message)] @@ -650,7 +645,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. + /// * `OnlyClusterOwner` error if the caller is not the cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. #[ink(message, payable)] pub fn cluster_set_params( @@ -680,7 +675,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. + /// * `OnlyClusterOwner` error if the caller is not the cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `ClusterIsNotEmpty` error if the removing cluster contains some Storage or CDN nodes. #[ink(message)] @@ -711,9 +706,8 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. + /// * `OnlyTrustedManagerOrClusterOwner` error if the caller is not a trusted manager or cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. - /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. /// * `NodeIsNotAddedToCluster(ClusterId)` error if the Storage node is not in this cluster. #[ink(message)] pub fn cluster_set_node_status( @@ -749,9 +743,8 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedClusterManager` error if the caller is not the cluster owner. + /// * `OnlyTrustedManagerOrClusterOwner` error if the caller is not a trusted manager or cluster owner. /// * `ClusterDoesNotExist` error if the cluster does not exist. - /// * `ClusterManagerIsNotTrusted` error if the caller is not a trusted node manager. /// * `CdnNodeIsNotAddedToCluster(ClusterId)` error if the CDN node is not in this cluster. #[ink(message)] pub fn cluster_set_cdn_node_status( @@ -1074,7 +1067,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedCdnNodeOwner` error if the caller is not the CDN node owner. + /// * `OnlyCdnNodeOwner` error if the caller is not the CDN node owner. /// * `CdnNodeDoesNotExist` error if the CDN node does not exist. /// * `CdnNodeIsAlreadyAddedToCluster(ClusterId)` error if the removing CDN node is added to some cluster. #[ink(message)] @@ -1105,7 +1098,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedCdnNodeOwner` error if the caller is not the CDN node owner. + /// * `OnlyCdnNodeOwner` error if the caller is not the CDN node owner. /// * `CdnNodeDoesNotExist` error if the CDN node does not exist. #[ink(message, payable)] pub fn cdn_node_set_params( @@ -1257,7 +1250,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedNodeOwner` error if the caller is not the Storage node owner. + /// * `OnlyNodeOwner` error if the caller is not the Storage node owner. /// * `NodeDoesNotExist` error if the Storage node does not exist. /// * `NodeIsAlreadyAddedToCluster(ClusterId)` error if the removing Storage node is added to some cluster. #[ink(message)] @@ -1288,7 +1281,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedNodeOwner` error if the caller is not the Storage node owner. + /// * `OnlyNodeOwner` error if the caller is not the Storage node owner. /// * `NodeDoesNotExist` error if the Storage node does not exist. #[ink(message, payable)] pub fn node_set_params( @@ -1587,7 +1580,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// Returns `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. + /// Returns `OnlySuperAdmin` error if the caller is not the Super-admin. #[ink(message)] pub fn admin_grant_permission( &mut self, @@ -1616,7 +1609,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// Returns `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. + /// Returns `OnlySuperAdmin` error if the caller is not the Super-admin. #[ink(message)] pub fn admin_revoke_permission( &mut self, @@ -1646,7 +1639,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. + /// * `OnlySuperAdmin` error if the caller is not the Super-admin. /// * `NodeDoesNotExist` error if the Storage node does not exist. /// * `NodeOwnerIsNotSuperAdmin` error if the owner of the targeting node is not the Super-admin. #[ink(message)] @@ -1678,7 +1671,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `UnauthorizedSuperAdmin` error if the caller is not the Super-admin. + /// * `OnlySuperAdmin` error if the caller is not the Super-admin. /// * `CdnNodeDoesNotExist` error if the Storage node does not exist. /// * `CdnNodeOwnerIsNotSuperAdmin` error if the owner of the targeting node is not the Super-admin. #[ink(message)] @@ -1747,7 +1740,7 @@ pub mod ddc_bucket { pub enum Error { BucketDoesNotExist, ClusterDoesNotExist, - ParamsTooBig, + ParamsSizeExceedsLimit, VNodeDoesNotExist, BondingPeriodNotFinished, BucketClusterAlreadyConnected, @@ -1760,8 +1753,6 @@ pub mod ddc_bucket { AccountDoesNotExist, ParamsDoesNotExist, UnauthorizedOwner, - UnauthorizedClusterManager, - ClusterManagerIsNotTrusted, TransferFailed, InsufficientBalance, InsufficientResources, @@ -1770,9 +1761,14 @@ pub mod ddc_bucket { NodeIsAlreadyAddedToCluster(ClusterId), CdnNodeIsNotAddedToCluster(ClusterId), CdnNodeIsAlreadyAddedToCluster(ClusterId), - UnauthorizedNodeOwner, - UnauthorizedCdnNodeOwner, - UnauthorizedSuperAdmin, + OnlyNodeOwner, + OnlyCdnNodeOwner, + OnlyTrustedManager, + OnlyClusterOwner, + OnlySuperAdmin, + OnlyTrustedManagerOrClusterOwner, + OnlyTrustedManagerOrClusterOwnerOrNodeOwner, + OnlyTrustedManagerOrClusterOwnerOrCdnNodeOwner, TopologyAlreadyExists, ClusterIsNotEmpty, TopologyIsNotCreated(ClusterId), @@ -1781,7 +1777,7 @@ pub mod ddc_bucket { VNodeIsAlreadyAssignedToNode(NodeKey), NodeHasNoAssignedVNodes(NodeKey), NodeOwnerIsNotSuperAdmin, - CdnNodeOwnerIsNotSuperAdmin + CdnNodeOwnerIsNotSuperAdmin, } pub type Result = core::result::Result; diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index 2d5eff5c..6ea4dd84 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -4227,7 +4227,7 @@ }, { "index": 2, - "name": "ParamsTooBig" + "name": "ParamsSizeExceedsLimit" }, { "index": 3, @@ -4287,7 +4287,7 @@ }, { "index": 17, - "name": "ClusterManagerIsNotTrusted" + "name": "OnlyTrustedManager" }, { "index": 18, From d2ecff8f6dc6ad54fa2f39565d5cb2250c3bb993 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Tue, 27 Jun 2023 15:33:21 +0200 Subject: [PATCH 34/89] chore(lib): unused errors removed --- bucket/ddc_bucket/bucket/entity.rs | 2 +- bucket/lib.rs | 33 ++++++++++++----------------- scripts/sdk/src/abi/ddc_bucket.json | 2 +- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/bucket/ddc_bucket/bucket/entity.rs b/bucket/ddc_bucket/bucket/entity.rs index 00335ac9..e6adc099 100644 --- a/bucket/ddc_bucket/bucket/entity.rs +++ b/bucket/ddc_bucket/bucket/entity.rs @@ -60,7 +60,7 @@ pub struct BucketStatus { impl Bucket { pub fn only_owner(&self, caller: AccountId) -> Result<()> { - if self.owner_id == caller { Ok(()) } else { Err(UnauthorizedOwner) } + if self.owner_id == caller { Ok(()) } else { Err(OnlyOwner) } } pub fn put_resource(&mut self, amount: Resource) { diff --git a/bucket/lib.rs b/bucket/lib.rs index 6a38b231..f1877a32 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -1738,29 +1738,14 @@ pub mod ddc_bucket { #[derive(Debug, PartialEq, Eq, Encode, Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum Error { - BucketDoesNotExist, - ClusterDoesNotExist, - ParamsSizeExceedsLimit, - VNodeDoesNotExist, - BondingPeriodNotFinished, - BucketClusterAlreadyConnected, - BucketClusterNotSetup, NodeDoesNotExist, CdnNodeDoesNotExist, NodeAlreadyExists, CdnNodeAlreadyExists, - FlowDoesNotExist, AccountDoesNotExist, ParamsDoesNotExist, - UnauthorizedOwner, - TransferFailed, - InsufficientBalance, - InsufficientResources, - Unauthorized, - NodeIsNotAddedToCluster(ClusterId), - NodeIsAlreadyAddedToCluster(ClusterId), - CdnNodeIsNotAddedToCluster(ClusterId), - CdnNodeIsAlreadyAddedToCluster(ClusterId), + ParamsSizeExceedsLimit, + OnlyOwner, OnlyNodeOwner, OnlyCdnNodeOwner, OnlyTrustedManager, @@ -1769,15 +1754,25 @@ pub mod ddc_bucket { OnlyTrustedManagerOrClusterOwner, OnlyTrustedManagerOrClusterOwnerOrNodeOwner, OnlyTrustedManagerOrClusterOwnerOrCdnNodeOwner, - TopologyAlreadyExists, + Unauthorized, + ClusterDoesNotExist, ClusterIsNotEmpty, TopologyIsNotCreated(ClusterId), + TopologyAlreadyExists, + NodeIsNotAddedToCluster(ClusterId), + NodeIsAlreadyAddedToCluster(ClusterId), + CdnNodeIsNotAddedToCluster(ClusterId), + CdnNodeIsAlreadyAddedToCluster(ClusterId), VNodeDoesNotExistsInCluster(ClusterId), VNodeInNotAssignedToNode(ClusterId, VNodeToken), VNodeIsAlreadyAssignedToNode(NodeKey), - NodeHasNoAssignedVNodes(NodeKey), NodeOwnerIsNotSuperAdmin, CdnNodeOwnerIsNotSuperAdmin, + BucketDoesNotExist, + BondingPeriodNotFinished, + TransferFailed, + InsufficientBalance, + InsufficientResources, } pub type Result = core::result::Result; diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index 6ea4dd84..9cd41484 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -4279,7 +4279,7 @@ }, { "index": 15, - "name": "UnauthorizedOwner" + "name": "OnlyOwner" }, { "index": 16, From 383f38a983ad117b896404998562570dba1e681d Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Tue, 27 Jun 2023 16:29:27 +0200 Subject: [PATCH 35/89] chore(cluster): permissions for adding and removing nodes are fixed --- bucket/ddc_bucket/bucket/messages.rs | 2 +- bucket/ddc_bucket/cluster/entity.rs | 6 +-- bucket/ddc_bucket/cluster/messages.rs | 64 +++++++++++------------- bucket/ddc_bucket/perm/entity.rs | 2 +- bucket/ddc_bucket/perm/messages.rs | 6 +-- bucket/ddc_bucket/tests/test_contract.rs | 14 +++--- bucket/lib.rs | 37 +++++++------- scripts/sdk/src/abi/ddc_bucket.json | 4 +- 8 files changed, 63 insertions(+), 72 deletions(-) diff --git a/bucket/ddc_bucket/bucket/messages.rs b/bucket/ddc_bucket/bucket/messages.rs index fe191953..55a47a77 100644 --- a/bucket/ddc_bucket/bucket/messages.rs +++ b/bucket/ddc_bucket/bucket/messages.rs @@ -183,7 +183,7 @@ impl DdcBucket { fn only_owner_or_cluster_manager(bucket: &Bucket, cluster: &Cluster) -> Result<()> { let caller = Self::env().caller(); - cluster.only_owner(caller) + cluster.only_manager(caller) .or_else(|_| bucket.only_owner(caller)) } diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 7952cc3e..083eb38f 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -8,7 +8,7 @@ use crate::ddc_bucket::node::entity::{Resource, NodeKey}; use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; use crate::ddc_bucket::params::store::Params; -use crate::ddc_bucket::Error::{OnlyClusterOwner, InsufficientBalance}; +use crate::ddc_bucket::Error::{OnlyClusterManager, InsufficientBalance}; use crate::ddc_bucket::{AccountId, Balance, VNodeToken, Result, Error::*}; pub type ClusterId = u32; @@ -77,10 +77,10 @@ impl Cluster { Ok(cluster) } - pub fn only_owner(&self, caller: AccountId) -> Result<()> { + pub fn only_manager(&self, caller: AccountId) -> Result<()> { (self.manager_id == caller) .then(|| ()) - .ok_or(OnlyClusterOwner) + .ok_or(OnlyClusterManager) } pub fn only_without_nodes(&self) -> Result<()> { diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 01c36414..2824e52e 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -52,17 +52,20 @@ impl DdcBucket { node_key: NodeKey, v_nodes: Vec, ) -> Result<()> { + let caller = Self::env().caller(); let mut node: Node = self.nodes.get(node_key)?; node.only_without_cluster()?; - self.only_trusted_manager(node.provider_id)?; + self.only_trusted_cluster_manager(node.provider_id)?; + + let mut cluster = self.clusters.get(cluster_id)?; + cluster.only_manager(caller)?; node.set_cluster(cluster_id, NodeStatusInCluster::ACTIVE); self.nodes.update(node_key, &node)?; - let mut cluster = self.clusters.get(cluster_id)?; cluster.add_node(node_key); - for v_node in &v_nodes { + for _v_node in &v_nodes { cluster.total_rent += node.rent_per_month; } self.clusters.update(cluster_id, &cluster)?; @@ -90,10 +93,9 @@ impl DdcBucket { node.only_with_cluster(cluster_id)?; - if !self.only_trusted_manager(node.provider_id).is_ok() - && !cluster.only_owner(caller).is_ok() + if !cluster.only_manager(caller).is_ok() && !node.only_owner(caller).is_ok() { - return Err(OnlyTrustedManagerOrClusterOwnerOrNodeOwner); + return Err(OnlyClusterManagerOrNodeOwner); } node.unset_cluster(); @@ -101,7 +103,7 @@ impl DdcBucket { cluster.remove_node(node_key); let v_nodes = self.topology_store.get_v_nodes_by_node(node_key); - for v_node in &v_nodes { + for _v_node in &v_nodes { cluster.total_rent -= node.rent_per_month; } self.clusters.update(cluster_id, &cluster)?; @@ -138,12 +140,7 @@ impl DdcBucket { let mut new_node = self.nodes.get(new_node_key)?; new_node.only_with_cluster(cluster_id)?; - - // Verify that the provider of the new node trusts the cluster manager - if !self.only_trusted_manager(new_node.provider_id).is_ok() - && !cluster.only_owner(caller).is_ok() { - return Err(OnlyTrustedManagerOrClusterOwner); - } + cluster.only_manager(caller)?; // Reserve resources on the new node. new_node.take_resource(cluster.resource_per_vnode)?; @@ -167,14 +164,18 @@ impl DdcBucket { cluster_id: ClusterId, cdn_node_key: CdnNodeKey, ) -> Result<()> { + let caller = Self::env().caller(); + let mut cdn_node: CdnNode = self.cdn_nodes.get(cdn_node_key)?; cdn_node.only_without_cluster()?; - self.only_trusted_manager(cdn_node.provider_id)?; + self.only_trusted_cluster_manager(cdn_node.provider_id)?; + + let mut cluster = self.clusters.get(cluster_id)?; + cluster.only_manager(caller)?; cdn_node.set_cluster(cluster_id, NodeStatusInCluster::ACTIVE); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; - let mut cluster = self.clusters.get(cluster_id)?; cluster.add_cdn_node(cdn_node_key); self.clusters.update(cluster_id, &cluster)?; @@ -199,10 +200,9 @@ impl DdcBucket { cdn_node.only_with_cluster(cluster_id)?; - if !self.only_trusted_manager(cdn_node.provider_id).is_ok() - && !cluster.only_owner(caller).is_ok() + if !cluster.only_manager(caller).is_ok() && !cdn_node.only_owner(caller).is_ok() { - return Err(OnlyTrustedManagerOrClusterOwnerOrCdnNodeOwner); + return Err(OnlyClusterManagerOrCdnNodeOwner); } cdn_node.unset_cluster(); @@ -227,7 +227,7 @@ impl DdcBucket { let caller = Self::env().caller(); let cluster = self.clusters.get(cluster_id)?; - cluster.only_owner(caller)?; + cluster.only_manager(caller)?; cluster.only_without_nodes()?; self.clusters.remove(cluster_id); @@ -251,11 +251,7 @@ impl DdcBucket { let mut node = self.nodes.get(node_key)?; let cluster = self.clusters.get(cluster_id)?; - - if !self.only_trusted_manager(node.provider_id).is_ok() - && !cluster.only_owner(caller).is_ok() { - return Err(OnlyTrustedManagerOrClusterOwner) - } + cluster.only_manager(caller)?; node.change_status_in_cluster(status_in_cluster.clone()); self.nodes.update(node_key, &node)?; @@ -280,11 +276,7 @@ impl DdcBucket { let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; let cluster = self.clusters.get(cluster_id)?; - - if !self.only_trusted_manager(cdn_node.provider_id).is_ok() - && !cluster.only_owner(caller).is_ok() { - return Err(OnlyTrustedManagerOrClusterOwner) - } + cluster.only_manager(caller)?; cdn_node.change_status_in_cluster(status_in_cluster.clone()); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; @@ -299,12 +291,12 @@ impl DdcBucket { } - pub fn message_grant_manager_permission( + pub fn message_grant_trusted_manager_permission( &mut self, manager: AccountId ) -> Result<()> { let grantor = Self::env().caller(); - let permission = Permission::ManagerTrustedBy(grantor); + let permission = Permission::ClusterManagerTrustedBy(grantor); self.grant_permission(manager, permission)?; Self::env().emit_event(PermissionGranted { @@ -316,12 +308,12 @@ impl DdcBucket { } - pub fn message_revoke_manager_permission( + pub fn message_revoke_trusted_manager_permission( &mut self, manager: AccountId ) -> Result<()> { let grantor = Self::env().caller(); - let permission = Permission::ManagerTrustedBy(grantor); + let permission = Permission::ClusterManagerTrustedBy(grantor); self.revoke_permission(manager, permission)?; Self::env().emit_event(PermissionRevoked { @@ -340,7 +332,7 @@ impl DdcBucket { ) -> Result<()> { let caller = Self::env().caller(); let mut cluster = self.clusters.get(cluster_id)?; - cluster.only_owner(caller)?; + cluster.only_manager(caller)?; cluster.set_params(cluster_params.clone())?; self.clusters.update(cluster_id, &cluster)?; @@ -360,7 +352,7 @@ impl DdcBucket { ) -> Result<()> { let caller = Self::env().caller(); let mut cluster = self.clusters.get(cluster_id)?; - cluster.only_owner(caller)?; + cluster.only_manager(caller)?; cluster.put_resource(resource); self.clusters.update(cluster_id, &cluster)?; @@ -473,7 +465,7 @@ impl DdcBucket { let caller = Self::env().caller(); let mut cluster = self.clusters.get(cluster_id)?; - cluster.only_owner(caller)?; + cluster.only_manager(caller)?; cluster.cdn_set_rate(cdn_usd_per_gb); self.clusters.update(cluster_id, &cluster)?; diff --git a/bucket/ddc_bucket/perm/entity.rs b/bucket/ddc_bucket/perm/entity.rs index 316470ba..d5bceb25 100644 --- a/bucket/ddc_bucket/perm/entity.rs +++ b/bucket/ddc_bucket/perm/entity.rs @@ -7,7 +7,7 @@ use crate::ddc_bucket::AccountId; #[derive(Copy, Clone, Encode, Decode)] #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] pub enum Permission { - ManagerTrustedBy(AccountId), + ClusterManagerTrustedBy(AccountId), SetExchangeRate, SuperAdmin, } diff --git a/bucket/ddc_bucket/perm/messages.rs b/bucket/ddc_bucket/perm/messages.rs index 1485fd02..474f2fbb 100644 --- a/bucket/ddc_bucket/perm/messages.rs +++ b/bucket/ddc_bucket/perm/messages.rs @@ -32,12 +32,12 @@ impl DdcBucket { .ok_or(Unauthorized) } - pub fn only_trusted_manager(&self, provider_id: AccountId) -> Result { + pub fn only_trusted_cluster_manager(&self, provider_id: AccountId) -> Result { let caller = Self::env().caller(); - let perm = Permission::ManagerTrustedBy(provider_id); + let perm = Permission::ClusterManagerTrustedBy(provider_id); self.perms.has_permission(caller, perm) .then(|| caller) - .ok_or(OnlyTrustedManager) + .ok_or(OnlyTrustedClusterManager) } } diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index f06de155..09cbbab3 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -61,7 +61,7 @@ fn new_cluster() -> TestCluster { for provider_id in [provider_id0, provider_id1, provider_id2] { set_caller_value(provider_id, CONTRACT_FEE_LIMIT); contract.node_trust_manager(manager); - let expected_perm = Permission::ManagerTrustedBy(provider_id); + let expected_perm = Permission::ClusterManagerTrustedBy(provider_id); assert!(contract.has_permission(manager, expected_perm)); } @@ -177,7 +177,7 @@ fn new_cluster_cdn() -> TestCluster { set_caller_value(provider_id, CONTRACT_FEE_LIMIT); contract.node_trust_manager(manager); - let expected_perm = Permission::ManagerTrustedBy(provider_id); + let expected_perm = Permission::ClusterManagerTrustedBy(provider_id); assert!(contract.has_permission(manager, expected_perm)); } @@ -387,7 +387,7 @@ fn cluster_create_works() { for provider_id in provider_ids { assert!( matches!(evs.pop().unwrap(), Event::PermissionGranted(ev) if ev == - PermissionGranted { account_id: ctx.manager, permission: Permission::ManagerTrustedBy(*provider_id) }) + PermissionGranted { account_id: ctx.manager, permission: Permission::ClusterManagerTrustedBy(*provider_id) }) ); } @@ -431,7 +431,7 @@ fn cluster_replace_node_only_manager() { vec![1, 2, 3], ctx.node_key2 ), - Err(OnlyTrustedManagerOrClusterOwner) + Err(OnlyClusterManager) ); } @@ -453,7 +453,7 @@ fn cluster_replace_node_only_trusted_manager() { vec![1, 2, 3], ctx.node_key2 ), - Err(OnlyTrustedManager) + Err(OnlyTrustedClusterManager) ); } @@ -551,7 +551,7 @@ fn cluster_management_validation_works() { vec![1, 2, 3], AccountId::from([0x0a; 32]) ), - Err(OnlyTrustedManagerOrClusterOwner), + Err(OnlyClusterManager), "only the manager can modify the cluster" ); @@ -822,7 +822,7 @@ fn cluster_add_node() { ctx.contract.node_trust_manager(ctx.manager); assert!( matches!(get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == - PermissionGranted { account_id: ctx.manager, permission: Permission::ManagerTrustedBy(new_provider_id) }) + PermissionGranted { account_id: ctx.manager, permission: Permission::ClusterManagerTrustedBy(new_provider_id) }) ); let mut node_keys = Vec::::new(); diff --git a/bucket/lib.rs b/bucket/lib.rs index f1877a32..0431e577 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -422,7 +422,7 @@ pub mod ddc_bucket { /// Creates a cluster of Storage nodes and CDN nodes. /// /// This endpoint creates a cluster of Storage nodes and CDN nodes with specific parameters. - /// The caller will be the cluster owner (cluster manager). In order to add a Storage or CDN node, the manager must be authorized by the node owner using the `trust_manager` endpoint or be the node owner. + /// The caller will be the cluster manager (cluster owner). In order to add a Storage or CDN node, the manager must be authorized by the node owner using the `trust_manager` endpoint or be the node owner. /// /// # Parameters /// @@ -470,7 +470,7 @@ pub mod ddc_bucket { /// # Errors /// /// * `ClusterDoesNotExist` error if the cluster does not exist. - /// * `OnlyTrustedManager` error if the caller is not a trusted manager. + /// * `OnlyTrustedClusterManager` error if the caller is not a trusted cluster manager. /// * `NodeDoesNotExist` error if the adding Storage node does not exist. /// * `NodeIsAlreadyAddedToCluster(ClusterId)` error if the adding Storage node is already added to this or another cluster. #[ink(message, payable)] @@ -504,7 +504,7 @@ pub mod ddc_bucket { /// # Errors /// /// * `ClusterDoesNotExist` error if the cluster does not exist. - /// * `OnlyTrustedManagerOrClusterOwnerOrNodeOwner` error if the caller is not a trusted manager, cluster owner or node owner. + /// * `OnlyClusterManagerOrNodeOwner` error if the caller is not the cluster manager or node owner. /// * `NodeDoesNotExist` error if the removing Storage node does not exist. /// * `NodeIsNotAddedToCluster(ClusterId)` error if the removing Storage node is not in this cluster. #[ink(message)] @@ -539,7 +539,7 @@ pub mod ddc_bucket { /// # Errors /// /// * `ClusterDoesNotExist` error if the cluster does not exist. - /// * `OnlyTrustedManagerOrClusterOwner` error if the caller is not a trusted manager or cluster owner. + /// * `OnlyClusterManager` error if the caller is not the cluster manager. /// * `NodeDoesNotExist` error if the new Storage node does not exist. /// * `NodeIsNotAddedToCluster(ClusterId)` error if the new Storage node is not added to this cluster. /// * `NodeIsAlreadyAddedToCluster(ClusterId)` error if the new Storage node is in another cluster. @@ -580,7 +580,7 @@ pub mod ddc_bucket { /// # Errors /// /// * `ClusterDoesNotExist` error if the cluster does not exist. - /// * `OnlyTrustedManager` error if the caller is not a trusted manager. + /// * `OnlyTrustedClusterManager` error if the caller is not a trusted cluster manager. /// * `CdnNodeDoesNotExist` error if the adding CDN node does not exist. /// * `CdnNodeIsAlreadyAddedToCluster(ClusterId)` error if the adding CDN node is already added to this or another cluster. #[ink(message, payable)] @@ -613,7 +613,7 @@ pub mod ddc_bucket { /// # Errors /// /// * `ClusterDoesNotExist` error if the cluster does not exist. - /// * `OnlyTrustedManagerOrClusterOwnerOrCdnNodeOwner` error if the caller is not a trusted manager, cluster owner or node owner. + /// * `OnlyClusterManagerOrCdnNodeOwner` error if the caller is not the cluster manager or node owner. /// * `CdnNodeDoesNotExist` error if the removing CDN node does not exist. /// * `CdnNodeIsNotAddedToCluster(ClusterId)` error if the removing CDN node is not in this cluster. #[ink(message)] @@ -645,7 +645,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `OnlyClusterOwner` error if the caller is not the cluster owner. + /// * `OnlyClusterManager` error if the caller is not the cluster manager. /// * `ClusterDoesNotExist` error if the cluster does not exist. #[ink(message, payable)] pub fn cluster_set_params( @@ -675,7 +675,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `OnlyClusterOwner` error if the caller is not the cluster owner. + /// * `OnlyClusterManager` error if the caller is not the cluster manager. /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `ClusterIsNotEmpty` error if the removing cluster contains some Storage or CDN nodes. #[ink(message)] @@ -706,7 +706,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `OnlyTrustedManagerOrClusterOwner` error if the caller is not a trusted manager or cluster owner. + /// * `OnlyClusterManager` error if the caller is not the cluster manager. /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `NodeIsNotAddedToCluster(ClusterId)` error if the Storage node is not in this cluster. #[ink(message)] @@ -743,7 +743,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `OnlyTrustedManagerOrClusterOwner` error if the caller is not a trusted manager or cluster owner. + /// * `OnlyClusterManager` error if the caller is not the cluster manager. /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `CdnNodeIsNotAddedToCluster(ClusterId)` error if the CDN node is not in this cluster. #[ink(message)] @@ -1501,11 +1501,11 @@ pub mod ddc_bucket { /// /// No errors. The endpoint is idempotent. #[ink(message, payable)] - pub fn grant_manager_permission( + pub fn grant_trusted_manager_permission( &mut self, manager: AccountId ) -> Result<()> { - self.message_grant_manager_permission(manager) + self.message_grant_trusted_manager_permission(manager) } /// Revokes permissions from cluster manager. @@ -1530,11 +1530,11 @@ pub mod ddc_bucket { /// /// No errors. The endpoint is idempotent. #[ink(message)] - pub fn revoke_manager_permission( + pub fn revoke_trusted_manager_permission( &mut self, manager: AccountId ) -> Result<()> { - self.message_revoke_manager_permission(manager) + self.message_revoke_trusted_manager_permission(manager) } } @@ -1748,12 +1748,11 @@ pub mod ddc_bucket { OnlyOwner, OnlyNodeOwner, OnlyCdnNodeOwner, - OnlyTrustedManager, - OnlyClusterOwner, + OnlyClusterManager, + OnlyTrustedClusterManager, OnlySuperAdmin, - OnlyTrustedManagerOrClusterOwner, - OnlyTrustedManagerOrClusterOwnerOrNodeOwner, - OnlyTrustedManagerOrClusterOwnerOrCdnNodeOwner, + OnlyClusterManagerOrNodeOwner, + OnlyClusterManagerOrCdnNodeOwner, Unauthorized, ClusterDoesNotExist, ClusterIsNotEmpty, diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index 9cd41484..4e27fe11 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -4287,7 +4287,7 @@ }, { "index": 17, - "name": "OnlyTrustedManager" + "name": "OnlyTrustedClusterManager" }, { "index": 18, @@ -4960,7 +4960,7 @@ } ], "index": 0, - "name": "ManagerTrustedBy" + "name": "ClusterManagerTrustedBy" }, { "index": 1, From 42fe5455665d601a96868a780da537fb3c0b6ee5 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Tue, 27 Jun 2023 16:38:19 +0200 Subject: [PATCH 36/89] chore(constructor): initialization of default entities is removed --- bucket/ddc_bucket/cluster/entity.rs | 8 ++--- bucket/ddc_bucket/cluster/messages.rs | 4 +-- bucket/ddc_bucket/tests/test_contract.rs | 6 ++-- bucket/lib.rs | 38 +++--------------------- scripts/sdk/src/abi/ddc_bucket.json | 2 +- 5 files changed, 14 insertions(+), 44 deletions(-) diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 083eb38f..006db9a6 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -22,7 +22,7 @@ pub struct Cluster { // storage nodes pub nodes_keys: Vec, - pub resource_per_vnode: Resource, + pub resource_per_v_node: Resource, pub resource_used: Resource, pub revenues: Cash, pub total_rent: Balance, @@ -63,7 +63,7 @@ impl Cluster { manager_id, cluster_params: ClusterParams::default(), nodes_keys: Vec::new(), - resource_per_vnode: 0, + resource_per_v_node: 0, resource_used: 0, revenues: Cash(0), total_rent: 0, @@ -129,12 +129,12 @@ impl Cluster { } pub fn put_resource(&mut self, amount: Resource) { - self.resource_per_vnode += amount; + self.resource_per_v_node += amount; } pub fn take_resource(&mut self, amount: Resource) -> Result<()> { let used = self.resource_used + amount; - if used > self.resource_per_vnode { + if used > self.resource_per_v_node { return Err(InsufficientResources); } self.resource_used = used; diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 2824e52e..b7704a43 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -135,7 +135,7 @@ impl DdcBucket { // Give back resources to the old node let mut old_node = self.nodes.get(old_node_key)?; - old_node.put_resource(cluster.resource_per_vnode); + old_node.put_resource(cluster.resource_per_v_node); self.nodes.update(old_node_key, &old_node)?; let mut new_node = self.nodes.get(new_node_key)?; @@ -143,7 +143,7 @@ impl DdcBucket { cluster.only_manager(caller)?; // Reserve resources on the new node. - new_node.take_resource(cluster.resource_per_vnode)?; + new_node.take_resource(cluster.resource_per_v_node)?; self.nodes.update(new_node_key, &new_node)?; } diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index 09cbbab3..ff712495 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -369,7 +369,7 @@ fn cluster_create_works() { manager_id: ctx.manager, node_keys: ctx.node_keys, v_nodes: ctx.vnodes_wrapper, - resource_per_vnode: ctx.reserved, + resource_per_v_node: ctx.reserved, resource_used: 0, revenues: Cash(0), total_rent: ctx.rent_per_vnode * ctx.vnodes.len() as Balance, @@ -520,7 +520,7 @@ fn cluster_reserve_works() { // Check the changed state of the cluster. let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; - assert_eq!(cluster.resource_per_vnode, 10 + 5); + assert_eq!(cluster.resource_per_v_node, 10 + 5); // Check the changed state of the nodes. let expected_resources = [ @@ -973,7 +973,7 @@ fn bucket_reserve_0_works() { cluster: Cluster { manager_id: AccountId::default(), v_nodes: vec![], - resource_per_vnode: 0, + resource_per_v_node: 0, resource_used: 0, revenues: Cash(0), total_rent: 0, diff --git a/bucket/lib.rs b/bucket/lib.rs index 0431e577..d70c1d4b 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -8,7 +8,6 @@ use ink_lang as ink; #[ink::contract] pub mod ddc_bucket { - use ink_prelude::string::ToString; use ink_prelude::vec::Vec; use scale::{Decode, Encode}; @@ -76,40 +75,11 @@ pub mod ddc_bucket { #[ink(constructor)] pub fn new() -> Self { ink_lang::utils::initialize_contract(|contract: &mut Self| { - let operator = Self::env().caller(); - - contract.committer_store.init(operator); - contract.protocol_store.init(operator, DEFAULT_BASIS_POINTS); - + let admin = Self::env().caller(); // Make the creator of this contract a super-admin. - let admin_id = Self::env().caller(); - contract - .perms - .grant_permission(admin_id, &Permission::SuperAdmin); - - // Reserve IDs 0. - let _ = contract.accounts.create_if_not_exist(AccountId::default()); - let _ = contract.cdn_nodes.create(AccountId::default(), AccountId::default(), "".to_string(), 0); - - let _ = contract - .nodes - .create( - AccountId::default(), - AccountId::default(), - NodeParams::from(""), - 0, - Balance::default(), - ) - .unwrap(); - let _ = contract - .clusters - .create( - AccountId::default(), - ClusterParams::from(""), - ) - .unwrap(); - let _ = contract.buckets.create(AccountId::default(), 0); - let _ = contract.bucket_params.create("".to_string()).unwrap(); + contract.perms.grant_permission(admin, &Permission::SuperAdmin); + contract.committer_store.init(admin); + contract.protocol_store.init(admin, DEFAULT_BASIS_POINTS); }) } } diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index 4e27fe11..f09ebb11 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -3396,7 +3396,7 @@ "typeName": "AccountId" }, { - "name": "resource_per_vnode", + "name": "resource_per_v_node", "type": 5, "typeName": "Resource" }, From 2a61a7e98b6f7882c7f3ed198e8d6a9959512d38 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Tue, 27 Jun 2023 18:27:47 +0200 Subject: [PATCH 37/89] chore(lib): legacy endpoints enabled --- bucket/lib.rs | 694 +++++++++++++++++++++----------------------- build-and-deploy.sh | 2 +- 2 files changed, 324 insertions(+), 372 deletions(-) diff --git a/bucket/lib.rs b/bucket/lib.rs index d70c1d4b..8ccd1ecb 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -23,11 +23,12 @@ pub mod ddc_bucket { use topology::store::*; use crate::ddc_bucket::cdn_node::store::CdnNodeStore; - use crate::ddc_bucket::network_fee::{NetworkFeeStore}; + use crate::ddc_bucket::network_fee::{NetworkFeeStore, FeeConfig}; use crate::ddc_bucket::perm::entity::Permission; use self::buckets_perms::store::BucketsPermsStore; use self::cdn_node::entity::{CdnNodeInfo, CdnNodeKey, CdnNodeParams}; + use self::account::entity::Account; use self::protocol::store::ProtocolStore; use self::topology::store::TopologyStore; @@ -129,148 +130,148 @@ pub mod ddc_bucket { } impl DdcBucket { - // /// Create a new bucket and return its `bucket_id`. - // /// - // /// The caller will be its first owner and payer of resources. - // /// - // /// `bucket_params` is configuration used by clients and nodes. See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema) - // /// - // /// The bucket can be connected to a single cluster (currently). Allocate cluster resources with the function `bucket_alloc_into_cluster` - // #[ink(message, payable)] - // pub fn bucket_create( - // &mut self, - // bucket_params: BucketParams, - // cluster_id: ClusterId, - // owner_id: Option, - // ) -> BucketId { - // self.message_bucket_create(bucket_params, cluster_id, owner_id) - // .unwrap() - // } - - // /// Change owner of the bucket - // /// - // /// Provide the account of new owner - // #[ink(message, payable)] - // pub fn bucket_change_owner(&mut self, bucket_id: BucketId, owner_id: AccountId) -> () { - // self.message_bucket_change_owner(bucket_id, owner_id) - // .unwrap() - // } - - // /// Allocate some resources of a cluster to a bucket. - // /// - // /// The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes). - // #[ink(message)] - // pub fn bucket_alloc_into_cluster(&mut self, bucket_id: BucketId, resource: Resource) -> () { - // self.message_bucket_alloc_into_cluster(bucket_id, resource) - // .unwrap() - // } - - // /// Settle the due costs of a bucket from its payer account to the cluster account. - // #[ink(message)] - // pub fn bucket_settle_payment(&mut self, bucket_id: BucketId) { - // self.message_bucket_settle_payment(bucket_id).unwrap() - // } - - // /// Change the `bucket_params`, which is configuration used by clients and nodes. - // /// - // /// See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema) - // #[ink(message, payable)] - // pub fn bucket_change_params(&mut self, bucket_id: BucketId, params: BucketParams) { - // self.message_bucket_change_params(bucket_id, params) - // .unwrap(); - // } - - // /// Get the current status of a bucket. - // #[ink(message)] - // pub fn bucket_get(&self, bucket_id: BucketId) -> Result { - // self.message_bucket_get(bucket_id) - // } - - // /// Iterate through all buckets. - // /// - // /// The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`. - // /// The optimal `limit` depends on the size of params. - // /// - // /// The results can be filtered by owner. Note that paging must still be completed fully. - // #[ink(message)] - // pub fn bucket_list( - // &self, - // offset: u32, - // limit: u32, - // filter_owner_id: Option, - // ) -> (Vec, u32) { - // self.message_bucket_list(offset, limit, filter_owner_id) - // } - - // /// Iterate through all buckets and return only those owned by owner - // /// - // /// This method returns bucket struct, not the status - // #[ink(message)] - // pub fn bucket_list_for_account(&self, owner_id: AccountId) -> Vec { - // self.message_bucket_list_for_account(owner_id) - // } - - // /// Set availiablity of the bucket - // #[ink(message)] - // pub fn bucket_set_availability( - // &mut self, - // bucket_id: BucketId, - // public_availability: bool, - // ) -> () { - // self.message_bucket_set_availability(bucket_id, public_availability) - // .unwrap() - // } - - // /// Set max resource cap to be charged by CDN for public bucket - // #[ink(message)] - // pub fn bucket_set_resource_cap( - // &mut self, - // bucket_id: BucketId, - // new_resource_cap: Resource, - // ) -> () { - // self.message_bucket_set_resource_cap(bucket_id, new_resource_cap) - // .unwrap() - // } - - // /// Set permission for the reader of the bucket - // #[ink(message)] - // pub fn get_bucket_writers(&mut self, bucket_id: BucketId) -> Vec { - // self.message_get_bucket_writers(bucket_id).unwrap() - // } - - // /// Set permission for the writer of the bucket - // #[ink(message)] - // pub fn bucket_set_writer_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { - // self.message_grant_writer_permission(bucket_id, writer) - // .unwrap() - // } - - // /// Revoke permission for the writer of the bucket - // #[ink(message)] - // pub fn bucket_revoke_writer_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { - // self.message_revoke_writer_permission(bucket_id, writer) - // .unwrap() - // } - - // /// Set permission for the reader of the bucket - // #[ink(message)] - // pub fn get_bucket_readers(&mut self, bucket_id: BucketId) -> Vec { - // self.message_get_bucket_readers(bucket_id).unwrap() - // } - - // /// Set permission for the reader of the bucket - // #[ink(message)] - // pub fn bucket_set_reader_perm(&mut self, bucket_id: BucketId, reader: AccountId) -> () { - // self.message_grant_reader_permission(bucket_id, reader) - // .unwrap() - // } - - // /// Revoke permission for the reader of the bucket - // #[ink(message)] - // pub fn bucket_revoke_reader_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { - // self.message_revoke_reader_permission(bucket_id, writer) - // .unwrap() - // } + /// Create a new bucket and return its `bucket_id`. + /// + /// The caller will be its first owner and payer of resources. + /// + /// `bucket_params` is configuration used by clients and nodes. See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema) + /// + /// The bucket can be connected to a single cluster (currently). Allocate cluster resources with the function `bucket_alloc_into_cluster` + #[ink(message, payable)] + pub fn bucket_create( + &mut self, + bucket_params: BucketParams, + cluster_id: ClusterId, + owner_id: Option, + ) -> BucketId { + self.message_bucket_create(bucket_params, cluster_id, owner_id) + .unwrap() + } + + /// Change owner of the bucket + /// + /// Provide the account of new owner + #[ink(message, payable)] + pub fn bucket_change_owner(&mut self, bucket_id: BucketId, owner_id: AccountId) -> () { + self.message_bucket_change_owner(bucket_id, owner_id) + .unwrap() + } + + /// Allocate some resources of a cluster to a bucket. + /// + /// The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes). + #[ink(message)] + pub fn bucket_alloc_into_cluster(&mut self, bucket_id: BucketId, resource: Resource) -> () { + self.message_bucket_alloc_into_cluster(bucket_id, resource) + .unwrap() + } + + /// Settle the due costs of a bucket from its payer account to the cluster account. + #[ink(message)] + pub fn bucket_settle_payment(&mut self, bucket_id: BucketId) { + self.message_bucket_settle_payment(bucket_id).unwrap() + } + + /// Change the `bucket_params`, which is configuration used by clients and nodes. + /// + /// See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema) + #[ink(message, payable)] + pub fn bucket_change_params(&mut self, bucket_id: BucketId, params: BucketParams) { + self.message_bucket_change_params(bucket_id, params) + .unwrap(); + } + + /// Get the current status of a bucket. + #[ink(message)] + pub fn bucket_get(&self, bucket_id: BucketId) -> Result { + self.message_bucket_get(bucket_id) + } + + /// Iterate through all buckets. + /// + /// The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`. + /// The optimal `limit` depends on the size of params. + /// + /// The results can be filtered by owner. Note that paging must still be completed fully. + #[ink(message)] + pub fn bucket_list( + &self, + offset: u32, + limit: u32, + filter_owner_id: Option, + ) -> (Vec, u32) { + self.message_bucket_list(offset, limit, filter_owner_id) + } + + /// Iterate through all buckets and return only those owned by owner + /// + /// This method returns bucket struct, not the status + #[ink(message)] + pub fn bucket_list_for_account(&self, owner_id: AccountId) -> Vec { + self.message_bucket_list_for_account(owner_id) + } + + /// Set availiablity of the bucket + #[ink(message)] + pub fn bucket_set_availability( + &mut self, + bucket_id: BucketId, + public_availability: bool, + ) -> () { + self.message_bucket_set_availability(bucket_id, public_availability) + .unwrap() + } + + /// Set max resource cap to be charged by CDN for public bucket + #[ink(message)] + pub fn bucket_set_resource_cap( + &mut self, + bucket_id: BucketId, + new_resource_cap: Resource, + ) -> () { + self.message_bucket_set_resource_cap(bucket_id, new_resource_cap) + .unwrap() + } + + /// Set permission for the reader of the bucket + #[ink(message)] + pub fn get_bucket_writers(&mut self, bucket_id: BucketId) -> Vec { + self.message_get_bucket_writers(bucket_id).unwrap() + } + + /// Set permission for the writer of the bucket + #[ink(message)] + pub fn bucket_set_writer_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { + self.message_grant_writer_permission(bucket_id, writer) + .unwrap() + } + + /// Revoke permission for the writer of the bucket + #[ink(message)] + pub fn bucket_revoke_writer_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { + self.message_revoke_writer_permission(bucket_id, writer) + .unwrap() + } + + /// Set permission for the reader of the bucket + #[ink(message)] + pub fn get_bucket_readers(&mut self, bucket_id: BucketId) -> Vec { + self.message_get_bucket_readers(bucket_id).unwrap() + } + + /// Set permission for the reader of the bucket + #[ink(message)] + pub fn bucket_set_reader_perm(&mut self, bucket_id: BucketId, reader: AccountId) -> () { + self.message_grant_reader_permission(bucket_id, reader) + .unwrap() + } + + /// Revoke permission for the reader of the bucket + #[ink(message)] + pub fn bucket_revoke_reader_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { + self.message_revoke_reader_permission(bucket_id, writer) + .unwrap() + } } // ---- End Bucket ---- @@ -778,37 +779,66 @@ pub mod ddc_bucket { self.message_cluster_list(offset, limit, filter_manager_id) } + /// As manager, reserve more resources for the cluster from the free capacity of nodes. + /// + /// The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes). + #[ink(message)] + pub fn cluster_reserve_resource(&mut self, cluster_id: ClusterId, amount: Resource) -> () { + self.message_cluster_reserve_resource(cluster_id, amount) + .unwrap() + } + + /// Trigger the distribution of revenues from the cluster to the providers. + #[ink(message)] + pub fn cluster_distribute_revenues(&mut self, cluster_id: ClusterId) { + self.message_cluster_distribute_revenues(cluster_id) + .unwrap() + } + + /// Set rate for streaming (price per gb) + #[ink(message, payable)] + pub fn cdn_set_rate(&mut self, cluster_id: ClusterId, usd_per_gb: Balance) -> () { + self.message_cdn_set_rate(cluster_id, usd_per_gb).unwrap() + } + + /// Get rate for streaming (price per gb) + #[ink(message, payable)] + pub fn cdn_get_rate(&self, cluster_id: ClusterId) -> Balance { + self.message_cdn_get_rate(cluster_id).unwrap() + } + /// As validator, charge payments from users and allocate undistributed payments to CDN nodes. + /// + /// As a result CDN cluster revenue increases, which can be distributed between CDN node providers via method cdn_cluster_distribute_revenues. + #[ink(message)] + pub fn cdn_cluster_put_revenue( + &mut self, + cluster_id: ClusterId, + aggregates_accounts: Vec<(AccountId, u128)>, + aggregates_nodes: Vec<(CdnNodeKey, u128)>, + aggregates_buckets: Vec<(BucketId, Resource)>, + era: u64, + ) -> () { + self.message_cdn_cluster_put_revenue( + cluster_id, + aggregates_accounts, + aggregates_nodes, + aggregates_buckets, + era, + ) + .unwrap() + } - // /// As manager, reserve more resources for the cluster from the free capacity of nodes. - // /// - // /// The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes). - // #[ink(message)] - // pub fn cluster_reserve_resource(&mut self, cluster_id: ClusterId, amount: Resource) -> () { - // self.message_cluster_reserve_resource(cluster_id, amount) - // .unwrap() - // } - - // /// As manager, re-assign a vnode to another physical node. - // /// - // /// The cluster manager can only use nodes of providers that trust him (see `node_trust_manager`), or any nodes if he is also SuperAdmin. - // #[ink(message)] - // pub fn cluster_replace_node( - // &mut self, - // cluster_id: ClusterId, - // v_nodes: Vec, - // new_node_key: NodeKey, - // ) -> () { - // self.message_cluster_replace_node(cluster_id, v_nodes, new_node_key) - // .unwrap() - // } - - // /// Trigger the distribution of revenues from the cluster to the providers. - // #[ink(message)] - // pub fn cluster_distribute_revenues(&mut self, cluster_id: ClusterId) { - // self.message_cluster_distribute_revenues(cluster_id) - // .unwrap() - // } + /// Trigger the distribution of revenues from the cluster to the CDN node providers. + /// + /// Anyone can call this method. + /// + /// Undistributed payments will be trasnferred, CDN cluster revenue will decrease. + #[ink(message)] + pub fn cdn_cluster_distribute_revenues(&mut self, cluster_id: ClusterId) { + self.message_cdn_cluster_distribute_revenues(cluster_id) + .unwrap() + } } // ---- End Cluster ---- @@ -835,124 +865,46 @@ pub mod ddc_bucket { provider_id: AccountId, } - impl DdcBucket { - // /// Create a new cluster and return its `cluster_id`. - // /// - // /// The caller will be its first manager. - // /// - // /// The CDN node ids are provided, which will form a cluster. - // #[ink(message, payable)] - // pub fn cdn_cluster_create(&mut self, cdn_node_keys: Vec) -> ClusterId { - // self.message_cdn_cluster_create(cdn_node_keys).unwrap() - // } - - // /// Set rate for streaming (price per gb) - // #[ink(message, payable)] - // pub fn cdn_set_rate(&mut self, cluster_id: ClusterId, usd_per_gb: Balance) -> () { - // self.message_cdn_set_rate(cluster_id, usd_per_gb).unwrap() - // } - - // /// Get rate for streaming (price per gb) - // #[ink(message, payable)] - // pub fn cdn_get_rate(&self, cluster_id: ClusterId) -> Balance { - // self.message_cdn_get_rate(cluster_id).unwrap() - // } - - // /// As validator, charge payments from users and allocate undistributed payments to CDN nodes. - // /// - // /// As a result CDN cluster revenue increases, which can be distributed between CDN node providers via method cdn_cluster_distribute_revenues. - // #[ink(message)] - // pub fn cdn_cluster_put_revenue( - // &mut self, - // cluster_id: ClusterId, - // aggregates_accounts: Vec<(AccountId, u128)>, - // aggregates_nodes: Vec<(CdnNodeKey, u128)>, - // aggregates_buckets: Vec<(BucketId, Resource)>, - // era: u64, - // ) -> () { - // self.message_cdn_cluster_put_revenue( - // cluster_id, - // aggregates_accounts, - // aggregates_nodes, - // aggregates_buckets, - // era, - // ) - // .unwrap() - // } - - // /// Trigger the distribution of revenues from the cluster to the CDN node providers. - // /// - // /// Anyone can call this method. - // /// - // /// Undistributed payments will be trasnferred, CDN cluster revenue will decrease. - // #[ink(message)] - // pub fn cdn_cluster_distribute_revenues(&mut self, cluster_id: ClusterId) { - // self.message_cdn_cluster_distribute_revenues(cluster_id) - // .unwrap() - // } - - // /// Get the current status of a cluster. - // #[ink(message)] - // pub fn cdn_cluster_get(&self, cluster_id: ClusterId) -> Result { - // self.message_cdn_cluster_get(cluster_id) - // } - - // /// Iterate through all clusters. - // /// - // /// The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`. - // /// The optimal `limit` depends on the size of params. - // /// - // /// The results can be filtered by manager. Note that paging must still be completed fully. - // #[ink(message)] - // pub fn cdn_cluster_list( - // &self, - // offset: u32, - // limit: u32, - // filter_manager_id: Option, - // ) -> (Vec, u32) { - // self.message_cdn_cluster_list(offset, limit, filter_manager_id) - // } - } // ---- End CDN Cluster ---- // ---- Committer ---- impl DdcBucket { - // /// CDN node operator sets the commit for current era. - // #[ink(message)] - // pub fn set_commit(&mut self, cdn_owner: AccountId, cdn_node_key: CdnNodeKey, commit: Commit) { - // self.message_set_commit(cdn_owner, cdn_node_key, commit); - // } - - // /// Return the last commit submitted by CDN node operator - // #[ink(message)] - // pub fn get_commit(&self, cdn_owner: AccountId) -> Vec<(CdnNodeKey, Commit)> { - // self.message_get_commit(cdn_owner) - // } - - // /// Return last era validated per CDN node - // #[ink(message)] - // pub fn get_validated_commit(&self, cdn_node_key: CdnNodeKey) -> EraAndTimestamp { - // self.message_get_validated_commit(cdn_node_key) - // } - - // /// Set the new configs for era - // #[ink(message)] - // pub fn set_era(&mut self, era_config: EraConfig) -> () { - // self.message_set_era(era_config).unwrap(); - // } - - // /// Return current status of an era - // #[ink(message)] - // pub fn get_era(&self) -> EraStatus { - // self.message_get_era() - // } - - // /// Return current era settings - // #[ink(message)] - // pub fn get_era_settings(&self) -> EraConfig { - // self.message_get_era_settings() - // } + /// CDN node operator sets the commit for current era. + #[ink(message)] + pub fn set_commit(&mut self, cdn_owner: AccountId, cdn_node_key: CdnNodeKey, commit: Commit) { + self.message_set_commit(cdn_owner, cdn_node_key, commit); + } + + /// Return the last commit submitted by CDN node operator + #[ink(message)] + pub fn get_commit(&self, cdn_owner: AccountId) -> Vec<(CdnNodeKey, Commit)> { + self.message_get_commit(cdn_owner) + } + + /// Return last era validated per CDN node + #[ink(message)] + pub fn get_validated_commit(&self, cdn_node_key: CdnNodeKey) -> EraAndTimestamp { + self.message_get_validated_commit(cdn_node_key) + } + + /// Set the new configs for era + #[ink(message)] + pub fn set_era(&mut self, era_config: EraConfig) -> () { + self.message_set_era(era_config).unwrap(); + } + + /// Return current status of an era + #[ink(message)] + pub fn get_era(&self) -> EraStatus { + self.message_get_era() + } + + /// Return current era settings + #[ink(message)] + pub fn get_era_settings(&self) -> EraConfig { + self.message_get_era_settings() + } } // ---- End Committer ---- @@ -1316,29 +1268,29 @@ pub mod ddc_bucket { // ---- Protocol ---- impl DdcBucket { - // /// Get the Fee Percentage Basis Points that will be charged by the protocol - // #[ink(message)] - // pub fn get_fee_bp(&self) -> u32 { - // self.message_get_fee_bp() - // } - - // /// Return the last commit submitted by CDN node operator - // #[ink(message)] - // pub fn set_fee_bp(&mut self, fee_bp: u32) -> () { - // self.message_set_fee_bp(fee_bp).unwrap(); - // } - - // /// Return fees accumulated by the protocol - // #[ink(message)] - // pub fn get_protocol_revenues(&self) -> Cash { - // self.message_get_fee_revenues() - // } - - // /// Pay the revenues accumulated by the protocol - // #[ink(message)] - // pub fn protocol_withdraw_revenues(&mut self, amount: u128) -> () { - // self.message_withdraw_revenues(amount).unwrap(); - // } + /// Get the Fee Percentage Basis Points that will be charged by the protocol + #[ink(message)] + pub fn get_fee_bp(&self) -> u32 { + self.message_get_fee_bp() + } + + /// Return the last commit submitted by CDN node operator + #[ink(message)] + pub fn set_fee_bp(&mut self, fee_bp: u32) -> () { + self.message_set_fee_bp(fee_bp).unwrap(); + } + + /// Return fees accumulated by the protocol + #[ink(message)] + pub fn get_protocol_revenues(&self) -> Cash { + self.message_get_fee_revenues() + } + + /// Pay the revenues accumulated by the protocol + #[ink(message)] + pub fn protocol_withdraw_revenues(&mut self, amount: u128) -> () { + self.message_withdraw_revenues(amount).unwrap(); + } } // ---- End Protocol ---- @@ -1354,52 +1306,52 @@ pub mod ddc_bucket { } impl DdcBucket { - // /// As user, deposit tokens on the account of the caller from the transaction value. This deposit - // /// can be used to pay for the services to buckets of the account. - // #[ink(message, payable)] - // pub fn account_deposit(&mut self) -> () { - // self.message_account_deposit().unwrap() - // } - - // /// As user, bond some amount of tokens from the withdrawable balance. These funds will be used to pay for CDN node service. - // #[ink(message, payable)] - // pub fn account_bond(&mut self, bond_amount: Balance) -> () { - // self.message_account_bond(bond_amount).unwrap() - // } - - // /// As user, unbond a specified amount of tokens. The tokens will be locked for some time, as defined by contract owner. - // #[ink(message, payable)] - // pub fn account_unbond(&mut self, amount_to_unbond: Cash) -> () { - // self.message_account_unbond(amount_to_unbond).unwrap() - // } - - // /// As user, move the unbonded tokens back to withdrawable balance state. - // /// - // /// This can be triggered after unbonded_timestamp - // #[ink(message, payable)] - // pub fn account_withdraw_unbonded(&mut self) -> () { - // self.message_account_withdraw_unbonded().unwrap() - // } - - // /// Get the current status of an account. - // #[ink(message)] - // pub fn account_get(&self, account_id: AccountId) -> Result { - // Ok(self.accounts.get(&account_id)?.clone()) - // } - - // /// Get the current conversion rate between the native currency and an external currency (USD). - // #[ink(message)] - // pub fn account_get_usd_per_cere(&self) -> Balance { - // self.message_account_get_usd_per_cere() - // } - - // /// As price oracle, set the current conversion rate between the native currency and an external currency (USD). - // /// - // /// This requires the permission SetExchangeRate or SuperAdmin. - // #[ink(message)] - // pub fn account_set_usd_per_cere(&mut self, usd_per_cere: Balance) { - // self.message_account_set_usd_per_cere(usd_per_cere); - // } + /// As user, deposit tokens on the account of the caller from the transaction value. This deposit + /// can be used to pay for the services to buckets of the account. + #[ink(message, payable)] + pub fn account_deposit(&mut self) -> () { + self.message_account_deposit().unwrap() + } + + /// As user, bond some amount of tokens from the withdrawable balance. These funds will be used to pay for CDN node service. + #[ink(message, payable)] + pub fn account_bond(&mut self, bond_amount: Balance) -> () { + self.message_account_bond(bond_amount).unwrap() + } + + /// As user, unbond a specified amount of tokens. The tokens will be locked for some time, as defined by contract owner. + #[ink(message, payable)] + pub fn account_unbond(&mut self, amount_to_unbond: Cash) -> () { + self.message_account_unbond(amount_to_unbond).unwrap() + } + + /// As user, move the unbonded tokens back to withdrawable balance state. + /// + /// This can be triggered after unbonded_timestamp + #[ink(message, payable)] + pub fn account_withdraw_unbonded(&mut self) -> () { + self.message_account_withdraw_unbonded().unwrap() + } + + /// Get the current status of an account. + #[ink(message)] + pub fn account_get(&self, account_id: AccountId) -> Result { + Ok(self.accounts.get(&account_id)?.clone()) + } + + /// Get the current conversion rate between the native currency and an external currency (USD). + #[ink(message)] + pub fn account_get_usd_per_cere(&self) -> Balance { + self.message_account_get_usd_per_cere() + } + + /// As price oracle, set the current conversion rate between the native currency and an external currency (USD). + /// + /// This requires the permission SetExchangeRate or SuperAdmin. + #[ink(message)] + pub fn account_set_usd_per_cere(&mut self, usd_per_cere: Balance) { + self.message_account_set_usd_per_cere(usd_per_cere); + } } // ---- End Billing ---- @@ -1653,29 +1605,29 @@ pub mod ddc_bucket { self.message_admin_transfer_cdn_node_ownership(cdn_node_key, new_owner) } - // /// As SuperAdmin, withdraw the funds held in custody in this contract. - // /// - // /// This is a temporary measure to allow migrating the funds to a new version of the contract. - // #[ink(message)] - // pub fn admin_withdraw(&mut self, amount: Balance) { - // self.message_admin_withdraw(amount).unwrap(); - // } + /// As SuperAdmin, withdraw the funds held in custody in this contract. + /// + /// This is a temporary measure to allow migrating the funds to a new version of the contract. + #[ink(message)] + pub fn admin_withdraw(&mut self, amount: Balance) { + self.message_admin_withdraw(amount).unwrap(); + } - // /// As SuperAdmin, set the network and cluster fee configuration. - // #[ink(message)] - // pub fn admin_set_fee_config(&mut self, config: FeeConfig) { - // self.message_admin_set_fee_config(config).unwrap(); - // } + /// As SuperAdmin, set the network and cluster fee configuration. + #[ink(message)] + pub fn admin_set_fee_config(&mut self, config: FeeConfig) { + self.message_admin_set_fee_config(config).unwrap(); + } } // ---- End Admin ---- // ---- Accounts ---- impl DdcBucket { - // /// Get all Account IDs stored in the SC - // #[ink(message, payable)] - // pub fn get_accounts(&self) -> Vec { - // self.message_get_accounts() - // } + /// Get all Account IDs stored in the SC + #[ink(message, payable)] + pub fn get_accounts(&self) -> Vec { + self.message_get_accounts() + } } // ---- End Accounts ---- diff --git a/build-and-deploy.sh b/build-and-deploy.sh index c4021826..48107b65 100755 --- a/build-and-deploy.sh +++ b/build-and-deploy.sh @@ -2,7 +2,7 @@ set -eu -# cargo +nightly-2023-02-07 test +cargo +nightly-2023-02-07 test cargo +nightly-2023-02-07 contract build --release --manifest-path bucket/Cargo.toml # cargo +nightly-2023-02-07 contract build --release --manifest-path ddc_nft_registry/Cargo.toml From 956905aac25ede44c97f2c51842416aa6a0b7b4e Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Tue, 27 Jun 2023 21:10:43 +0200 Subject: [PATCH 38/89] chore(test): basic test scenario is recovered --- bucket/ddc_bucket/cluster/messages.rs | 4 +- bucket/ddc_bucket/node/entity.rs | 4 +- bucket/ddc_bucket/perm/messages.rs | 12 +- bucket/ddc_bucket/tests/env_utils.rs | 14 + bucket/ddc_bucket/tests/test_admin.rs | 166 +- bucket/ddc_bucket/tests/test_contract.rs | 2473 +++++++++++----------- bucket/ddc_bucket/tests/test_currency.rs | 104 +- 7 files changed, 1428 insertions(+), 1349 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index b7704a43..b03631c0 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -61,7 +61,7 @@ impl DdcBucket { let mut cluster = self.clusters.get(cluster_id)?; cluster.only_manager(caller)?; - node.set_cluster(cluster_id, NodeStatusInCluster::ACTIVE); + node.set_cluster(cluster_id, NodeStatusInCluster::ADDING); self.nodes.update(node_key, &node)?; cluster.add_node(node_key); @@ -173,7 +173,7 @@ impl DdcBucket { let mut cluster = self.clusters.get(cluster_id)?; cluster.only_manager(caller)?; - cdn_node.set_cluster(cluster_id, NodeStatusInCluster::ACTIVE); + cdn_node.set_cluster(cluster_id, NodeStatusInCluster::ADDING); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; cluster.add_cdn_node(cdn_node_key); diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index 969b8521..134ecdaa 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -46,13 +46,13 @@ pub enum NodeStatusInCluster { impl SpreadAllocate for NodeStatusInCluster { fn allocate_spread(_: &mut KeyPtr) -> Self { - NodeStatusInCluster::ACTIVE + NodeStatusInCluster::ADDING } } impl Default for NodeStatusInCluster { fn default() -> Self { - NodeStatusInCluster::ACTIVE + NodeStatusInCluster::ADDING } } diff --git a/bucket/ddc_bucket/perm/messages.rs b/bucket/ddc_bucket/perm/messages.rs index 474f2fbb..caed1e79 100644 --- a/bucket/ddc_bucket/perm/messages.rs +++ b/bucket/ddc_bucket/perm/messages.rs @@ -1,27 +1,19 @@ //! The public interface for permission management. -use ink_lang::codegen::{EmitEvent, StaticEnv}; +use ink_lang::codegen::{StaticEnv}; -use crate::ddc_bucket::{AccountId, DdcBucket, PermissionGranted, PermissionRevoked, Result, Error::* }; +use crate::ddc_bucket::{AccountId, DdcBucket, Result, Error::* }; use crate::ddc_bucket::perm::entity::Permission; impl DdcBucket { pub fn grant_permission(&mut self, account_id: AccountId, permission: Permission) -> Result<()> { self.perms.grant_permission(account_id, &permission); - Self::env().emit_event(PermissionGranted { - account_id, - permission - }); Ok(()) } pub fn revoke_permission(&mut self, account_id: AccountId, permission: Permission) -> Result<()> { self.perms.revoke_permission(account_id, &permission); - Self::env().emit_event(PermissionRevoked { - account_id, - permission - }); Ok(()) } diff --git a/bucket/ddc_bucket/tests/env_utils.rs b/bucket/ddc_bucket/tests/env_utils.rs index fd58af7c..aba4b2f1 100644 --- a/bucket/ddc_bucket/tests/env_utils.rs +++ b/bucket/ddc_bucket/tests/env_utils.rs @@ -81,6 +81,20 @@ pub fn print_events(events: &[Event]) { Event::CdnClusterCreated(ev) => println!("EVENT {:?}", ev), Event::CdnClusterDistributeRevenues(ev) => println!("EVENT {:?}", ev), Event::CdnNodeCreated(ev) => println!("EVENT {:?}", ev), + Event::ClusterNodeAdded(ev) => println!("EVENT {:?}", ev), + Event::ClusterCdnNodeAdded(ev) => println!("EVENT {:?}", ev), + Event::ClusterNodeRemoved(ev) => println!("EVENT {:?}", ev), + Event::ClusterCdnNodeRemoved(ev) => println!("EVENT {:?}", ev), + Event::ClusterParamsSet(ev) => println!("EVENT {:?}", ev), + Event::ClusterRemoved(ev) => println!("EVENT {:?}", ev), + Event::ClusterNodeStatusSet(ev) => println!("EVENT {:?}", ev), + Event::ClusterCdnNodeStatusSet(ev) => println!("EVENT {:?}", ev), + Event::CdnNodeRemoved(ev) => println!("EVENT {:?}", ev), + Event::CdnNodeParamsSet(ev) => println!("EVENT {:?}", ev), + Event::NodeRemoved(ev) => println!("EVENT {:?}", ev), + Event::NodeParamsSet(ev) => println!("EVENT {:?}", ev), + Event::NodeOwnershipTransferred(ev) => println!("EVENT {:?}", ev), + Event::CdnNodeOwnershipTransferred(ev) => println!("EVENT {:?}", ev), } } } diff --git a/bucket/ddc_bucket/tests/test_admin.rs b/bucket/ddc_bucket/tests/test_admin.rs index 4e4d6097..76d0383f 100644 --- a/bucket/ddc_bucket/tests/test_admin.rs +++ b/bucket/ddc_bucket/tests/test_admin.rs @@ -1,118 +1,118 @@ -use ink_lang as ink; +// use ink_lang as ink; -use crate::ddc_bucket::*; +// use crate::ddc_bucket::*; -use super::env_utils::*; +// use super::env_utils::*; -#[ink::test] -fn admin_init_works() { - let contract = setup(); +// #[ink::test] +// fn admin_init_works() { +// let contract = setup(); - // The deployer is SuperAdmin. - assert!(contract.has_permission(admin_id(), Permission::SuperAdmin)); - assert!(!contract.has_permission(not_admin_id(), Permission::SuperAdmin)); +// // The deployer is SuperAdmin. +// assert!(contract.has_permission(admin_id(), Permission::SuperAdmin)); +// assert!(!contract.has_permission(not_admin_id(), Permission::SuperAdmin)); - // The SuperAdmin has all other permissions, too. - assert!(contract.has_permission(admin_id(), Permission::SetExchangeRate)); - assert!(!contract.has_permission(not_admin_id(), Permission::SetExchangeRate)); -} +// // The SuperAdmin has all other permissions, too. +// assert!(contract.has_permission(admin_id(), Permission::SetExchangeRate)); +// assert!(!contract.has_permission(not_admin_id(), Permission::SetExchangeRate)); +// } -#[ink::test] -fn admin_withdraw_works() { - let mut contract = setup(); - assert_eq!(balance_of(contract_id()), 10); +// #[ink::test] +// fn admin_withdraw_works() { +// let mut contract = setup(); +// assert_eq!(balance_of(contract_id()), 10); - set_caller(admin_id()); +// set_caller(admin_id()); - contract.admin_withdraw(9); +// contract.admin_withdraw(9); - assert_eq!(balance_of(contract_id()), 1); -} +// assert_eq!(balance_of(contract_id()), 1); +// } -#[ink::test] -#[should_panic] -fn admin_withdraw_only_admin() { - let mut contract = setup(); +// #[ink::test] +// #[should_panic] +// fn admin_withdraw_only_admin() { +// let mut contract = setup(); - set_caller(not_admin_id()); +// set_caller(not_admin_id()); - contract.admin_withdraw(9); // panic. -} +// contract.admin_withdraw(9); // panic. +// } -#[ink::test] -fn admin_grant_works() { - let mut contract = setup(); - let permission = Permission::SuperAdmin; +// #[ink::test] +// fn admin_grant_works() { +// let mut contract = setup(); +// let permission = Permission::SuperAdmin; - set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); +// set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); - let new_admin_id = not_admin_id(); +// let new_admin_id = not_admin_id(); - contract.admin_grant_permission(new_admin_id, permission); +// contract.admin_grant_permission(new_admin_id, permission); - // Check the last event. - let ev = get_events().pop().unwrap(); - assert!(matches!(ev, Event::PermissionGranted(ev) if ev == - PermissionGranted { account_id: not_admin_id(), permission })); +// // Check the last event. +// let ev = get_events().pop().unwrap(); +// assert!(matches!(ev, Event::PermissionGranted(ev) if ev == +// PermissionGranted { account_id: not_admin_id(), permission })); - assert!(contract.has_permission(new_admin_id, permission)); +// assert!(contract.has_permission(new_admin_id, permission)); - set_caller(new_admin_id); +// set_caller(new_admin_id); - contract.admin_withdraw(9); -} +// contract.admin_withdraw(9); +// } -#[ink::test] -#[should_panic] -fn admin_grant_only_admin() { - let mut contract = setup(); +// #[ink::test] +// #[should_panic] +// fn admin_grant_only_admin() { +// let mut contract = setup(); - set_caller_value(not_admin_id(), CONTRACT_FEE_LIMIT); +// set_caller_value(not_admin_id(), CONTRACT_FEE_LIMIT); - contract.admin_grant_permission(get_accounts().charlie, Permission::SuperAdmin); // panic. -} +// contract.admin_grant_permission(get_accounts().charlie, Permission::SuperAdmin); // panic. +// } -#[ink::test] -#[should_panic] -fn admin_revoke_works() { - let mut contract = setup(); - let permission = Permission::SuperAdmin; +// #[ink::test] +// #[should_panic] +// fn admin_revoke_works() { +// let mut contract = setup(); +// let permission = Permission::SuperAdmin; - set_caller(admin_id()); +// set_caller(admin_id()); - contract.admin_revoke_permission(admin_id(), permission); +// contract.admin_revoke_permission(admin_id(), permission); - // Check the last event. - let ev = get_events().pop().unwrap(); - assert!(matches!(ev, Event::PermissionRevoked(ev) if ev == - PermissionRevoked { account_id: not_admin_id(), permission })); +// // Check the last event. +// let ev = get_events().pop().unwrap(); +// assert!(matches!(ev, Event::PermissionRevoked(ev) if ev == +// PermissionRevoked { account_id: not_admin_id(), permission })); - assert!(!contract.has_permission(admin_id(), permission)); +// assert!(!contract.has_permission(admin_id(), permission)); - // Cannot withdraw because no more permission. - set_caller(admin_id()); +// // Cannot withdraw because no more permission. +// set_caller(admin_id()); - contract.admin_withdraw(9); // panic. -} +// contract.admin_withdraw(9); // panic. +// } -#[ink::test] -#[should_panic] -fn admin_revoke_only_admin() { - let mut contract = setup(); +// #[ink::test] +// #[should_panic] +// fn admin_revoke_only_admin() { +// let mut contract = setup(); - set_caller_value(not_admin_id(), CONTRACT_FEE_LIMIT); +// set_caller_value(not_admin_id(), CONTRACT_FEE_LIMIT); - contract.admin_revoke_permission(admin_id(), Permission::SuperAdmin); // panic. -} +// contract.admin_revoke_permission(admin_id(), Permission::SuperAdmin); // panic. +// } -fn setup() -> DdcBucket { - set_caller(admin_id()); - set_callee(contract_id()); - let contract = DdcBucket::new(); - set_balance(contract_id(), 10); - contract -} +// fn setup() -> DdcBucket { +// set_caller(admin_id()); +// set_callee(contract_id()); +// let contract = DdcBucket::new(); +// set_balance(contract_id(), 10); +// contract +// } -fn not_admin_id() -> AccountId { - get_accounts().bob -} \ No newline at end of file +// fn not_admin_id() -> AccountId { +// get_accounts().bob +// } \ No newline at end of file diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index ff712495..9d73e31a 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -23,249 +23,286 @@ const KB_PER_GB: Balance = 1_048_576; struct TestCluster { contract: DdcBucket, - manager: AccountId, + manager_id: AccountId, cluster_id: ClusterId, + cluster_params: ClusterParams, provider_id0: AccountId, provider_id1: AccountId, provider_id2: AccountId, node_key0: NodeKey, node_key1: NodeKey, node_key2: NodeKey, - rent_per_vnode: Balance, - node_keys: Vec, - vnodes: Vec, - vnodes_wrapper: Vec>, - node_params0: &'static str, - node_params1: &'static str, - node_params2: &'static str, + rent_per_v_node: Balance, + nodes_keys: Vec, + node_params0: NodeParams, + node_params1: NodeParams, + node_params2: NodeParams, + cluster_v_nodes: Vec, + v_nodes_by_nodes: Vec>, capacity: u32, - reserved: u32, + reserved_resource: u32, } fn new_cluster() -> TestCluster { - let accounts = get_accounts(); - set_balance(accounts.charlie, 1000 * TOKEN); - set_balance(accounts.django, 1000 * TOKEN); - let provider_id0 = accounts.alice; - let provider_id1 = accounts.bob; - let provider_id2 = accounts.charlie; - let manager = accounts.django; - - let mut contract = setup(); - - // Provide a Node. - let rent_per_vnode: Balance = 10 * TOKEN; - let node_params0 = "{\"url\":\"https://ddc.cere.network/bucket/{BUCKET_ID}\"}"; + + let mut contract: DdcBucket = setup(); + + let provider_id0 = AccountId::from([0xae, 0x7d, 0xe8, 0x17, 0xa4, 0xa5, 0x12, 0x57, 0xd2, 0x49, 0x64, 0x28, 0x3b, 0x25, 0x69, 0x09, 0xdf, 0x0c, 0x99, 0x97, 0xc0, 0x3e, 0x2b, 0x88, 0x02, 0x02, 0xee, 0x10, 0xf4, 0x4d, 0x72, 0x48]); + let provider_id1 = AccountId::from([0xc4, 0xba, 0xfd, 0x6a, 0xa1, 0x5a, 0x14, 0xd6, 0xee, 0xf2, 0xea, 0x92, 0xb7, 0xc6, 0x84, 0x51, 0x68, 0x39, 0xbe, 0x96, 0xd6, 0xbf, 0xca, 0xa3, 0x68, 0xd2, 0x4f, 0xff, 0x09, 0x85, 0xa7, 0x1e]); + let provider_id2 = AccountId::from([0xfa, 0x01, 0x28, 0xf8, 0xe1, 0x32, 0xc6, 0x81, 0x21, 0x06, 0xa5, 0xce, 0xae, 0x6d, 0xcf, 0xf3, 0xd2, 0xc0, 0x1b, 0xb0, 0x13, 0xf2, 0xd7, 0x75, 0x6f, 0x20, 0xf9, 0x50, 0x00, 0xd6, 0xc7, 0x2b]); + let manager_id = AccountId::from([0xd2, 0xc5, 0xea, 0xa2, 0x0c, 0xd0, 0x4e, 0xfb, 0x3f, 0x10, 0xb8, 0xad, 0xa9, 0xa4, 0x4f, 0xe0, 0x85, 0x41, 0x1f, 0x59, 0xf2, 0x34, 0x1a, 0x92, 0xa3, 0x48, 0x4f, 0x04, 0x51, 0x87, 0x68, 0x54]); + + set_balance(provider_id0, 1000 * TOKEN); + set_balance(provider_id1, 1000 * TOKEN); + set_balance(provider_id2, 1000 * TOKEN); + set_balance(manager_id, 1000 * TOKEN); + + let rent_per_v_node: Balance = 10 * TOKEN; + let reserved_resource = 10; let capacity = 100; - for provider_id in [provider_id0, provider_id1, provider_id2] { - set_caller_value(provider_id, CONTRACT_FEE_LIMIT); - contract.node_trust_manager(manager); - let expected_perm = Permission::ClusterManagerTrustedBy(provider_id); - assert!(contract.has_permission(manager, expected_perm)); - } + // Create the 1st storage node + let node_key0 = AccountId::from([0x0a; 32]); + let node_params0 = NodeParams::from("{\"url\":\"https://ddc.cere.network/bucket/{BUCKET_ID}\"}"); + let capacity0 = 100; set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); - let node_key0 = contract.node_create( - AccountId::from([0x0a; 32]), - rent_per_vnode, - node_params0.to_string(), + contract.node_create( + node_key0, + node_params0.clone(), capacity, - NodeStatusInCluster::ADDING, - ); + rent_per_v_node + ).unwrap(); - // Provide another Node. - let node_params1 = "{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"; - set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); - let node_key1 = contract.node_create( - AccountId::from([0x0b; 32]), - rent_per_vnode, - node_params1.to_string(), + // Create the 2nd storage node + let node_key1 = AccountId::from([0x0b; 32]); + let node_params1 = NodeParams::from("{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"); + let capacity1 = 100; + set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); + contract.node_create( + node_key1, + node_params1.clone(), capacity, - NodeStatusInCluster::ADDING, - ); + rent_per_v_node + ).unwrap(); - // Provide another Node. - let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; - set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); + // Create the 3rd storage node + let node_key2 = AccountId::from([0x0c; 32]); + let node_params2 = NodeParams::from("{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"); + set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); let node_key2 = contract.node_create( - AccountId::from([0x0c; 32]), - rent_per_vnode, - node_params2.to_string(), + node_key2, + node_params2.clone(), capacity, - NodeStatusInCluster::ADDING, - ); + rent_per_v_node, + ).unwrap(); - // Create a Cluster. - let node_keys = vec![ - AccountId::from([0x0a; 32]), - AccountId::from([0x0b; 32]), - AccountId::from([0x0c; 32]) - ]; - let cluster_params = "{}"; - let mut vnodes_wrapper = Vec::>::new(); - - let vnodes_for_first_node = vec![1, 2, 3]; - let vnodes_for_second_node = vec![4, 5, 6]; - let vnodes_for_third_node = vec![7, 8, 9]; - - vnodes_wrapper.push(vnodes_for_first_node); - vnodes_wrapper.push(vnodes_for_second_node); - vnodes_wrapper.push(vnodes_for_third_node); - - set_caller_value(manager, CONTRACT_FEE_LIMIT); + // Create a Cluster + let cluster_params = ClusterParams::from("{}"); + set_caller_value(manager_id, CONTRACT_FEE_LIMIT); let cluster_id = contract.cluster_create( - manager, - vnodes_wrapper.clone(), - vec![node_key0, node_key1, node_key2], - cluster_params.to_string(), - ); - - let reserved = 10; - contract.cluster_reserve_resource(cluster_id, reserved); + cluster_params.clone(), + ).unwrap(); - let mut vnodes = Vec::::new(); - - for v_nodes_vec in vnodes_wrapper.clone() { - for v_node in v_nodes_vec { - vnodes.push(v_node.clone()); - } - } - - TestCluster { - contract, - manager, - cluster_id, - provider_id0, - provider_id1, - provider_id2, - node_key0, - node_key1, - node_key2, - rent_per_vnode, - vnodes_wrapper, - vnodes, - node_keys, - node_params0, - node_params1, - node_params2, - capacity, - reserved, - } -} - -fn new_cluster_cdn() -> TestCluster { - let accounts = get_accounts(); - set_balance(accounts.charlie, 1000 * TOKEN); - set_balance(accounts.django, 1000 * TOKEN); - let provider_id0 = accounts.alice; - let provider_id1 = accounts.bob; - let provider_id2 = accounts.charlie; - let manager = accounts.django; - - let mut contract = setup(); - - // Provide a Node. - let rent_per_vnode: Balance = 10 * TOKEN; - let node_params0 = "{\"url\":\"https://ddc.cere.network/bucket/{BUCKET_ID}\"}"; - let capacity = 100; + // Grant trusted manager_id permission from node providers to the cluster manager_id for provider_id in [provider_id0, provider_id1, provider_id2] { set_caller_value(provider_id, CONTRACT_FEE_LIMIT); - - contract.node_trust_manager(manager); + contract.grant_trusted_manager_permission(manager_id).unwrap(); let expected_perm = Permission::ClusterManagerTrustedBy(provider_id); - assert!(contract.has_permission(manager, expected_perm)); + assert!(contract.has_permission(manager_id, expected_perm)); } - set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); + println!("\n"); - let cdn_node_key0 = AccountId::from([0x0a; 32]); - let node_key0 = contract.cdn_node_create(cdn_node_key0, node_params0.to_string()); + // Add the 1st node to the Cluster + let v_nodes0 = vec![1, 2, 3]; + set_caller_value(manager_id, CONTRACT_FEE_LIMIT); + contract.cluster_add_node( + cluster_id, + node_key0, + v_nodes0.clone() + ).unwrap(); - // Provide another Node. - let node_params1 = "{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"; - set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); - let cdn_node_key1 = AccountId::from([0x0b; 32]); + // Add the 2nd node to the Cluster + let v_nodes1 = vec![4, 5, 6]; + set_caller_value(manager_id, CONTRACT_FEE_LIMIT); + contract.cluster_add_node( + cluster_id, + node_key1, + v_nodes1.clone() + ).unwrap(); - let node_key1 = contract.cdn_node_create(cdn_node_key1, node_params1.to_string()); - // Provide another Node. - let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; - set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); - - let cdn_node_key2 = AccountId::from([0x0c; 32]); - - let node_key2 = contract.cdn_node_create(cdn_node_key2, node_params2.to_string()); - - // Create a Cluster. - let _cluster_params = "{}"; - - // TODO: adjust after cdn cluster topology and node addition + // Add the 3rd node to the Cluster + let v_nodes2 = vec![7, 8, 9]; + set_caller_value(manager_id, CONTRACT_FEE_LIMIT); + contract.cluster_add_node( + cluster_id, + node_key2, + v_nodes2.clone() + ).unwrap(); - let vnodes = vec![1, 2, 3, 4, 5, 6]; - let node_keys = vec![node_key0, node_key1, node_key2]; - let mut vnodes_wrapper = Vec::>::new(); - vnodes_wrapper.push(vnodes); + set_caller(manager_id); + contract.cluster_reserve_resource(cluster_id, reserved_resource); - let mut vnodes_wrapper = Vec::>::new(); - let vnodes_for_first_node = vec![1, 2, 3]; - let vnodes_for_second_node = vec![4, 5, 6]; - let vnodes_for_third_node = vec![7, 8, 9]; - - vnodes_wrapper.push(vnodes_for_first_node); - vnodes_wrapper.push(vnodes_for_second_node); - vnodes_wrapper.push(vnodes_for_third_node); - - set_caller_value(manager, CONTRACT_FEE_LIMIT); - - let cluster_id = contract.cdn_cluster_create( - vec![ - AccountId::from([0x0a; 32]), - AccountId::from([0x0b; 32]), - AccountId::from([0x0c; 32]) - ] - ); + let nodes_keys = vec![ + node_key0, + node_key1, + node_key2 + ]; - let reserved = 10; + let v_nodes_by_nodes = vec![ + v_nodes0.clone(), + v_nodes1.clone(), + v_nodes2.clone() + ]; - let mut vnodes = Vec::::new(); + let mut cluster_v_nodes = Vec::::new(); + cluster_v_nodes.extend(v_nodes0); + cluster_v_nodes.extend(v_nodes1); + cluster_v_nodes.extend(v_nodes2); - for v_nodes_vec in vnodes_wrapper.clone() { - for v_node in v_nodes_vec { - vnodes.push(v_node.clone()); - } - } TestCluster { contract, - manager, + manager_id, cluster_id, + cluster_params, provider_id0, provider_id1, provider_id2, node_key0, node_key1, node_key2, - rent_per_vnode, - vnodes_wrapper, + rent_per_v_node, + v_nodes_by_nodes, + cluster_v_nodes, + nodes_keys, node_params0, node_params1, node_params2, capacity, - reserved, - node_keys, - vnodes, + reserved_resource, } } +// fn new_cluster_cdn() -> TestCluster { +// let accounts = get_accounts(); +// set_balance(accounts.charlie, 1000 * TOKEN); +// set_balance(accounts.django, 1000 * TOKEN); +// let provider_id0 = accounts.alice; +// let provider_id1 = accounts.bob; +// let provider_id2 = accounts.charlie; +// let manager_id = accounts.django; + +// let mut contract = setup(); + +// // Provide a Node. +// let rent_per_v_node: Balance = 10 * TOKEN; +// let node_params0 = "{\"url\":\"https://ddc.cere.network/bucket/{BUCKET_ID}\"}"; +// let capacity = 100; + +// for provider_id in [provider_id0, provider_id1, provider_id2] { +// set_caller_value(provider_id, CONTRACT_FEE_LIMIT); + +// contract.node_trust_manager(manager_id); +// let expected_perm = Permission::ClusterManagerTrustedBy(provider_id); +// assert!(contract.has_permission(manager_id, expected_perm)); +// } + +// set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); + +// let cdn_node_key0 = AccountId::from([0x0a; 32]); + +// let node_key0 = contract.cdn_node_create(cdn_node_key0, node_params0.to_string()); + +// // Provide another Node. +// let node_params1 = "{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"; +// set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); + +// let cdn_node_key1 = AccountId::from([0x0b; 32]); + +// let node_key1 = contract.cdn_node_create(cdn_node_key1, node_params1.to_string()); + +// // Provide another Node. +// let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; +// set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); + +// let cdn_node_key2 = AccountId::from([0x0c; 32]); + +// let node_key2 = contract.cdn_node_create(cdn_node_key2, node_params2.to_string()); + +// // Create a Cluster. +// let _cluster_params = "{}"; + +// // TODO: adjust after cdn cluster topology and node addition + +// let vnodes = vec![1, 2, 3, 4, 5, 6]; + +// let node_keys = vec![node_key0, node_key1, node_key2]; +// let mut vnodes_wrapper = Vec::>::new(); +// vnodes_wrapper.push(vnodes); + +// let mut vnodes_wrapper = Vec::>::new(); + +// let vnodes_for_first_node = vec![1, 2, 3]; +// let vnodes_for_second_node = vec![4, 5, 6]; +// let vnodes_for_third_node = vec![7, 8, 9]; + +// vnodes_wrapper.push(vnodes_for_first_node); +// vnodes_wrapper.push(vnodes_for_second_node); +// vnodes_wrapper.push(vnodes_for_third_node); + +// set_caller_value(manager_id, CONTRACT_FEE_LIMIT); + +// let cluster_id = contract.cdn_cluster_create( +// vec![ +// AccountId::from([0x0a; 32]), +// AccountId::from([0x0b; 32]), +// AccountId::from([0x0c; 32]) +// ] +// ); + +// let reserved = 10; + +// let mut vnodes = Vec::::new(); + +// for v_nodes_vec in vnodes_wrapper.clone() { +// for v_node in v_nodes_vec { +// vnodes.push(v_node.clone()); +// } +// } + +// TestCluster { +// contract, +// manager_id, +// cluster_id, +// provider_id0, +// provider_id1, +// provider_id2, +// node_key0, +// node_key1, +// node_key2, +// rent_per_v_node, +// vnodes_wrapper, +// node_params0, +// node_params1, +// node_params2, +// capacity, +// reserved, +// node_keys, +// vnodes, +// } +// } + struct TestBucket { bucket_id: BucketId, owner_id: AccountId, @@ -301,17 +338,16 @@ fn new_bucket(ctx: &mut TestCluster) -> TestBucket { #[ink::test] fn cluster_create_works() { let ctx = new_cluster(); - let provider_ids = &[ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; + let providers_ids = &[ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; let node_keys = &[ctx.node_key0, ctx.node_key1, ctx.node_key2]; - let node_params = &[ctx.node_params0, ctx.node_params1, ctx.node_params2]; + let node_params = &[ctx.node_params0.clone(), ctx.node_params1.clone(), ctx.node_params2.clone()]; - assert_eq!(ctx.cluster_id, 1, "cluster_id must start at 1"); - assert_eq!(ctx.node_key0, AccountId::from([0x0a; 32]), "node_id must start at 1"); - assert_ne!(ctx.node_key0, ctx.node_key1, "nodes must have unique IDs"); + assert_eq!(ctx.cluster_id, 0, "cluster_id must start at 0"); - // Check the nodes. + // Check cluster nodes { let node0 = ctx.contract.node_get(ctx.node_key0)?; + let v_nodes0 = ctx.contract.get_v_nodes_by_node(ctx.node_key0); assert_eq!( node0, @@ -319,1078 +355,1115 @@ fn cluster_create_works() { node_key: ctx.node_key0, node: Node { provider_id: ctx.provider_id0, - rent_per_month: ctx.rent_per_vnode, - free_resource: ctx.capacity - ctx.reserved * 3, - status: NodeStatusInCluster::ADDING, - node_params: ctx.node_params0.to_string(), - } + rent_per_month: ctx.rent_per_v_node, + free_resource: ctx.capacity - ctx.reserved_resource * 3, + node_params: ctx.node_params0.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + v_nodes: v_nodes0 } ); let node1 = ctx.contract.node_get(ctx.node_key1)?; + let v_nodes1 = ctx.contract.get_v_nodes_by_node(ctx.node_key1); + assert_eq!( node1, NodeInfo { node_key: ctx.node_key1, node: Node { provider_id: ctx.provider_id1, - rent_per_month: ctx.rent_per_vnode, - free_resource: ctx.capacity - ctx.reserved * 3, - status: NodeStatusInCluster::ADDING, - node_params: ctx.node_params1.to_string(), - } + rent_per_month: ctx.rent_per_v_node, + free_resource: ctx.capacity - ctx.reserved_resource * 3, + node_params: ctx.node_params1.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + v_nodes: v_nodes1 } ); let node2 = ctx.contract.node_get(ctx.node_key2)?; + let v_nodes2 = ctx.contract.get_v_nodes_by_node(ctx.node_key2); + assert_eq!( node2, NodeInfo { node_key: ctx.node_key2, node: Node { provider_id: ctx.provider_id2, - rent_per_month: ctx.rent_per_vnode, - free_resource: ctx.capacity - ctx.reserved * 3, - status: NodeStatusInCluster::ADDING, - node_params: ctx.node_params2.to_string(), - } + rent_per_month: ctx.rent_per_v_node, + free_resource: ctx.capacity - ctx.reserved_resource * 3, + node_params: ctx.node_params2.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + v_nodes: v_nodes2 } ); } - // Check the initial state of the cluster. + // Check the cluster { let cluster = ctx.contract.cluster_get(ctx.cluster_id)?; + let cluster_v_nodes = ctx.contract.get_v_nodes_by_cluster(ctx.cluster_id); assert_eq!( cluster, ClusterInfo { cluster_id: ctx.cluster_id, cluster: Cluster { - manager_id: ctx.manager, - node_keys: ctx.node_keys, - v_nodes: ctx.vnodes_wrapper, - resource_per_v_node: ctx.reserved, + manager_id: ctx.manager_id, + nodes_keys: ctx.nodes_keys, + resource_per_v_node: ctx.reserved_resource, resource_used: 0, + cluster_params: ctx.cluster_params.clone(), revenues: Cash(0), - total_rent: ctx.rent_per_vnode * ctx.vnodes.len() as Balance, + total_rent: ctx.rent_per_v_node * ctx.cluster_v_nodes.len() as Balance, + cdn_nodes_keys: Vec::new(), + cdn_usd_per_gb: 104_857_600, + cdn_resources_used: 0, + cdn_revenues: Cash(0), }, - params: "{}".to_string(), + cluster_v_nodes } ); } - // Check the events. - let mut evs = get_events(); - evs.reverse(); // Work with pop(). - - // Providers trust Manager. - for provider_id in provider_ids { - assert!( - matches!(evs.pop().unwrap(), Event::PermissionGranted(ev) if ev == - PermissionGranted { account_id: ctx.manager, permission: Permission::ClusterManagerTrustedBy(*provider_id) }) - ); - } + // Check emitted events + let mut events = get_events(); + events.reverse(); // Work with pop(). - // Nodes created. + // Node created event for i in 0..3 { - assert!(matches!(evs.pop().unwrap(), Event::NodeCreated(ev) if ev == + assert!(matches!(events.pop().unwrap(), Event::NodeCreated(ev) if ev == NodeCreated { node_key: node_keys[i], - provider_id: provider_ids[i], - rent_per_month: ctx.rent_per_vnode, - node_params: node_params[i].to_string() + provider_id: providers_ids[i], + rent_per_month: ctx.rent_per_v_node, + node_params: node_params[i].clone() }) ); } - // Cluster setup. + // Cluster created event assert!( - matches!(evs.pop().unwrap(), Event::ClusterCreated(ev) if ev == - ClusterCreated { cluster_id: ctx.cluster_id, manager: ctx.manager, cluster_params: "{}".to_string() }) - ); - - assert!( - matches!(evs.pop().unwrap(), Event::ClusterReserveResource(ev) if ev == - ClusterReserveResource { cluster_id: ctx.cluster_id, resource: ctx.reserved }) - ); - - assert_eq!(evs.len(), 0, "all events must be checked"); -} - -#[ink::test] -fn cluster_replace_node_only_manager() { - let mut ctx = new_cluster(); - let not_manager = get_accounts().alice; - set_caller_value(not_manager, 0); - - // Reassign a vnode from node1 to node2. - assert_eq!( - ctx.contract - .message_cluster_replace_node( - ctx.cluster_id, - vec![1, 2, 3], - ctx.node_key2 - ), - Err(OnlyClusterManager) - ); -} - -#[ink::test] -fn cluster_replace_node_only_trusted_manager() { - let mut ctx = new_cluster(); - - // The provider stops trusting the manager. - set_caller(ctx.provider_id2); - ctx.contract.node_distrust_manager(ctx.manager); - - set_caller_value(ctx.manager, 0); - - // The manager cannot use nodes of the provider. - assert_eq!( - ctx.contract - .message_cluster_replace_node( - ctx.cluster_id, - vec![1, 2, 3], - ctx.node_key2 - ), - Err(OnlyTrustedClusterManager) + matches!(events.pop().unwrap(), Event::ClusterCreated(ev) if ev == + ClusterCreated { + cluster_id: ctx.cluster_id, + manager: ctx.manager_id, + cluster_params: ctx.cluster_params.clone() + }) ); -} - -#[ink::test] -fn cluster_replace_node_works() { - let mut ctx = new_cluster(); - set_caller_value(ctx.manager, 0); - - // Reassign a vnode from node1 to node2. - ctx.contract - .cluster_replace_node(ctx.cluster_id, vec![1, 3], ctx.node_key2); - - // Check the last event. - let ev = get_events().pop().unwrap(); - assert!(matches!(ev, Event::ClusterNodeReplaced(ev) if ev == - ClusterNodeReplaced { cluster_id: ctx.cluster_id, node_key: ctx.node_key2 })); - - let vnodes_for_replaced = vec![2]; - let vnodes_for_second_node = vec![4, 5, 6]; - let vnodes_for_third_node = vec![7, 8, 9]; - let vnodes_for_third_dup = vec![1, 3]; - - let vnodes = vec![ - vnodes_for_replaced, - vnodes_for_second_node, - vnodes_for_third_node, - vnodes_for_third_dup, - ]; - // Check the changed state of the cluster. - let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; - println!("cluster.v_nodes: {:?}", cluster.v_nodes.clone()); - println!("cluster.node_keys: {:?}", cluster.node_keys.clone()); - assert_eq!(&cluster.v_nodes, &vnodes, "a vnode must be replaced"); - - // Check the changed state of the nodes. - let expected_resources = [ - (ctx.node_key0, 100 - 10), - (ctx.node_key1, 100 - 10 - 10 - 10), - (ctx.node_key2, 100 - 10 - 10 - 10 - 10 - 10), - ]; - - for (node_key, available) in expected_resources { - let node_status = ctx.contract.node_get(node_key).unwrap(); - assert_eq!( - node_status.node.free_resource, available, - "resources must have shifted between nodes" - ); - } -} - -#[ink::test] -fn cluster_reserve_works() { - let mut ctx = new_cluster(); - set_caller_value(ctx.manager, 0); - - // Reserve more resources. - ctx.contract.cluster_reserve_resource(ctx.cluster_id, 5); - - // Check the last event. - let ev = get_events().pop().unwrap(); - assert!(matches!(ev, Event::ClusterReserveResource(ev) if ev == - ClusterReserveResource { cluster_id: ctx.cluster_id, resource: 5 })); - - // Check the changed state of the cluster. - let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; - assert_eq!(cluster.resource_per_v_node, 10 + 5); - - // Check the changed state of the nodes. - let expected_resources = [ - (ctx.node_key0, 100 - 40 - 5), - (ctx.node_key1, 100 - 40 - 5), - (ctx.node_key2, 100 - 40 - 5), - ]; - for (node_id, available) in expected_resources { - assert_eq!( - ctx.contract.node_get(node_id)?.node.free_resource, - available, - "more resources must be reserved from the nodes" + // Permission granted event + for provider_id in providers_ids { + assert!( + matches!(events.pop().unwrap(), Event::PermissionGranted(ev) if ev == + PermissionGranted { + account_id: ctx.manager_id, + permission: Permission::ClusterManagerTrustedBy(*provider_id) + }) ); } -} - -#[ink::test] -fn cluster_management_validation_works() { - let mut ctx = new_cluster(); - - let not_manager = ctx.provider_id0; - set_caller_value(not_manager, 0); - - assert_eq!( - ctx.contract - .message_cluster_replace_node( - ctx.cluster_id, - vec![1, 2, 3], - AccountId::from([0x0a; 32]) - ), - Err(OnlyClusterManager), - "only the manager can modify the cluster" - ); - - set_caller_value(ctx.manager, 0); - - let bad_node_id = AccountId::from([0x0d; 32]); - assert_eq!( - ctx.contract - .message_cluster_replace_node( - ctx.cluster_id, - vec![1, 2, 3], - bad_node_id - ), - Err(NodeDoesNotExist), - "cluster replacement node must exist" - ); - - assert_eq!( - ctx.contract - .message_cluster_create(vec![vec![1, 2, 3]], vec![bad_node_id], vec![1, 2, 3], "".to_string()), - Err(NodeDoesNotExist), - "cluster initial nodes must exist" - ); -} - -#[ink::test] -fn cdn_cluster_gas_converter_works() { - println!("Creating new cdn cluster"); - - let mut ctx = new_cluster_cdn(); - - println!("Got cdn cluster back"); - // The provider stops trusting the manager. - println!("Cdn cluster id is {}", ctx.cluster_id); - set_caller(ctx.manager); - ctx.contract.cdn_set_rate(ctx.cluster_id, 3_750_000_000); - set_caller(ctx.provider_id0); - let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); - - let usd_per_cere = TOKEN / 100; - set_caller(ctx.provider_id0); - ctx.contract.account_set_usd_per_cere(usd_per_cere); - - let usd_amount = ctx.contract.account_get_usd_per_cere(); - println!("Current usd amount is {}", usd_amount); - - println!("The current rate is {}", rate); - - let usd_per_kb = rate / KB_PER_GB; - println!("The current rate per kb {}", usd_per_kb); - - let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); - println!("The current cere rate per kb {}", cere_per_kb); -} - -#[ink::test] -fn cdn_cluster_payment_works() { - println!("Creating new cdn cluster"); - - let mut ctx = new_cluster_cdn(); - - println!("Got cdn cluster back"); - // The provider stops trusting the manager. - println!("Cdn cluster id is {}", ctx.cluster_id); - set_caller(ctx.provider_id0); - let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); - - let usd_per_cere = TOKEN / 100; - set_caller(ctx.provider_id0); - ctx.contract.account_set_usd_per_cere(usd_per_cere); - - let usd_amount = ctx.contract.account_get_usd_per_cere(); - println!("Current usd amount is {}", usd_amount); - - println!("The current rate is {}", rate); - - let usd_per_kb = rate / KB_PER_GB; - println!("The current rate per kb {}", usd_per_kb); - - let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); - println!("The current cere rate per kb {}", cere_per_kb); - - set_caller_value(ctx.provider_id0, 10 * TOKEN); - ctx.contract.account_deposit(); - - set_caller(ctx.provider_id0); - ctx.contract.account_bond(5 * TOKEN); - - set_caller(ctx.provider_id0); - ctx.contract.set_fee_bp(1_000); - - let mut account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); - println!("{:?}", account); - - ctx.contract.cdn_cluster_put_revenue( - ctx.cluster_id, - vec![(ctx.provider_id0, 1000), (ctx.provider_id0, 541643)], - vec![(ctx.node_key0, 1000), (ctx.node_key1, 541643)], - vec![], - 5, - ); - account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); - println!("{:?}", account); - - let cdn_cluster_list_one = ctx.contract.cdn_cluster_list(0, 10, None); - print!("Cluster list one {:?}", cdn_cluster_list_one); - let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); - let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); - - println!("Node 1 {:?}", node0); - println!("Node 2 {:?}", node1); - // let cdn_cluster0 = ctx.contract.cdn_clusters.get(ctx.cluster_id); - // print!("{:?}", cdn_cluster0); - // let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); - // print!("{:?}", cdn_cluster0); - // print!("{:?}", cdn_cluster_list); - - let validated_commit_node0 = ctx.contract.get_validated_commit(ctx.node_key0); - print!("Validated commit {:?}", validated_commit_node0); - - let fee = ctx.contract.get_fee_bp(); - print!("Protocol fee in basis points {:?}", fee); - - let protocol_revenues = ctx.contract.get_protocol_revenues(); - print!("Protocol revenues are {:?}", protocol_revenues); - - set_caller(ctx.provider_id0); - ctx.contract.cdn_cluster_distribute_revenues(0); - - let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); - let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); - println!("{:?}", node0); - println!("{:?}", node1); - - let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); - print!("{:?}", cdn_cluster_list); - - account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); - // let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); - // let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); - println!("{:?}", account); - // let account1 = ctx.contract.accounts.get(&ctx.provider_id1).unwrap(); - // println!("{:?}", account1); - // let account_balance = ink_env::balance(&ctx.provider_id0); - // println!("{:?}", account_balance); -} - -fn bucket_settle_payment(ctx: &mut TestCluster, test_bucket: &TestBucket) { - // Go to the future when some revenues are due. - advance_block::(); - // Pay the due thus far. - set_caller_value(ctx.manager, CONTRACT_FEE_LIMIT); - ctx.contract.bucket_settle_payment(test_bucket.bucket_id); -} - -#[ink::test] -fn bucket_pays_cluster() { - let ctx = &mut new_cluster(); - let test_bucket = &new_bucket(ctx); - do_bucket_pays_cluster(ctx, test_bucket, 1).unwrap(); -} - -#[ink::test] -fn bucket_pays_cluster_at_new_rate() { - let ctx = &mut new_cluster(); - let test_bucket = &new_bucket(ctx); - - // Set up an exchange rate manager. - set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); - ctx.contract - .admin_grant_permission(admin_id(), Permission::SetExchangeRate); - - // Change the currency exchange rate. - let usd_per_cere = 2; - set_caller(admin_id()); - ctx.contract.account_set_usd_per_cere(usd_per_cere * TOKEN); - - do_bucket_pays_cluster(ctx, test_bucket, usd_per_cere).unwrap(); -} - -fn do_bucket_pays_cluster( - ctx: &mut TestCluster, - test_bucket: &TestBucket, - usd_per_cere: Balance, -) -> Result<()> { - let expected_rent = ctx.rent_per_vnode * ctx.vnodes.len() as Balance; - - // Check the state before payment. - let before = ctx - .contract - .account_get(test_bucket.owner_id)? - .deposit - .peek(); - let bucket = ctx.contract.bucket_get(test_bucket.bucket_id)?.bucket; - assert_eq!(bucket.owner_id, test_bucket.owner_id); - /* TODO: Not testable at the moment, see struct BucketInStatus. - assert_eq!(bucket.flow, - Flow { - from: test_bucket.owner_id, - schedule: Schedule::new(0, expected_rent), - }); - */ - let timestamp_before = block_timestamp::(); - bucket_settle_payment(ctx, &test_bucket); - let timestamp_after = block_timestamp::(); - - // Check the last event. - let ev = get_events().pop().unwrap(); - assert!(matches!(ev, Event::BucketSettlePayment(ev) if ev == - BucketSettlePayment { bucket_id: test_bucket.bucket_id, cluster_id: ctx.cluster_id })); - - // Check the state after payment. - let after = ctx - .contract - .account_get(test_bucket.owner_id)? - .deposit - .peek(); - let spent = before - after; - /* TODO: Not testable at the moment, see struct BucketInStatus. - let bucket = ctx.contract.bucket_get(test_bucket.bucket_id)?.bucket; - assert_eq!(bucket.flow, - Flow { - from: test_bucket.owner_id, - schedule: Schedule::new(BLOCK_TIME, expected_rent), - }); - */ - let timespan = timestamp_after - timestamp_before; - let expect_revenues_usd = expected_rent * timespan as u128 / MS_PER_MONTH as u128; - let expect_revenues = expect_revenues_usd / usd_per_cere; - assert!(expect_revenues > 0); - assert_eq!( - expect_revenues, spent, - "revenues must come from the bucket owner" - ); - - let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; - assert_eq!( - cluster.revenues.peek(), - expect_revenues, - "must get revenues into the cluster" - ); - Ok(()) -} - -#[ink::test] -fn cluster_add_node() { - let ctx = &mut new_cluster(); - - let new_provider_id = get_accounts().frank; - set_balance(new_provider_id, 1000 * TOKEN); - - let rent_per_month = 100; - let node_params = "new_node"; - let capacity = 1000; - let status = NodeStatusInCluster::ACTIVE; - - set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - let new_node_id = ctx.contract.node_create( - AccountId::from([0x0d; 32]), - rent_per_month, - node_params.to_string(), - capacity, - status, - ); - - set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.node_trust_manager(ctx.manager); - assert!( - matches!(get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == - PermissionGranted { account_id: ctx.manager, permission: Permission::ClusterManagerTrustedBy(new_provider_id) }) - ); - - let mut node_keys = Vec::::new(); - node_keys.push(ctx.node_key0); - node_keys.push(ctx.node_key1); - node_keys.push(ctx.node_key2); - node_keys.push(new_node_id); - - let mut v_nodes = ctx.vnodes_wrapper.clone(); - v_nodes.push(vec![10, 11, 12]); - - set_caller_value(ctx.manager, CONTRACT_FEE_LIMIT); - ctx.contract - .cluster_add_node(ctx.cluster_id, node_keys.clone(), v_nodes.clone()); - - let cluster_status = ctx.contract.cluster_get(ctx.cluster_id).unwrap(); - assert!(matches!(cluster_status.clone().cluster.node_keys.len(), 4)); - assert!(matches!(cluster_status.clone().cluster.v_nodes.len(), 4)); -} - -#[ink::test] -fn cluster_pays_providers() { - let ctx = &mut new_cluster(); - let test_bucket = &new_bucket(ctx); - bucket_settle_payment(ctx, &test_bucket); - - // Get state before the distribution. - let to_distribute = ctx - .contract - .cluster_get(ctx.cluster_id)? - .cluster - .revenues - .peek(); - let before0 = balance_of(ctx.provider_id0); - let before1 = balance_of(ctx.provider_id1); - let before2 = balance_of(ctx.provider_id2); - let before_mgmt = balance_of(ctx.manager); - - let skip_events = get_events::().len(); - - // Set a network fee. - let network_fee_bp = 100; // 1% - let cluster_management_fee_bp = 200; // 2% - set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); - ctx.contract.admin_set_fee_config(FeeConfig { - network_fee_bp, - network_fee_destination: AccountId::default(), - cluster_management_fee_bp, - }); - - let burned_fee = to_distribute * network_fee_bp / 10_000; - let manager_fee = (to_distribute - burned_fee) * cluster_management_fee_bp / 10_000; - let provider_fee = (to_distribute - burned_fee - manager_fee) / 3; - - // Distribute the revenues of the cluster to providers. - ctx.contract.cluster_distribute_revenues(ctx.cluster_id); - - // Check the last events. - let mut evs = get_events(); - evs.reverse(); // Work with pop(). - evs.truncate(evs.len() - skip_events); - let expected_recipients = vec![ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; - - for provider_id in expected_recipients { - assert!( - matches!(evs.pop().unwrap(), Event::ClusterDistributeRevenues(ev) if ev == - ClusterDistributeRevenues { cluster_id: ctx.cluster_id, provider_id }) + // Cluster node added event + for i in 0..3 { + assert!(matches!(events.pop().unwrap(), Event::ClusterNodeAdded(ev) if ev == + ClusterNodeAdded { + cluster_id: ctx.cluster_id, + node_key: node_keys[i] + }) ); } - assert_eq!(evs.len(), 0, "all events must be checked"); - - // Get state after the distribution. - let rounding_error = ctx - .contract - .cluster_get(ctx.cluster_id)? - .cluster - .revenues - .peek(); - let earned0 = balance_of(ctx.provider_id0) - before0; - let earned1 = balance_of(ctx.provider_id1) - before1; - let earned2 = balance_of(ctx.provider_id2) - before2; - let earned_mgmt = balance_of(ctx.manager) - before_mgmt; - - assert!(provider_fee > 0, "provider must earn something"); - assert_eq!( - earned0, provider_fee, - "providers must earn the correct amount" - ); - assert_eq!( - earned1, provider_fee, - "providers must earn the correct amount" - ); - assert_eq!( - earned2, provider_fee, - "providers must earn the correct amount" - ); - - assert!(burned_fee > 0, "the network must earn something"); - assert!(manager_fee > 0, "the manager must earn something"); - assert_eq!( - earned_mgmt, manager_fee, - "the manager must earn the correct amount" - ); - - assert!(to_distribute > 0); - assert!( - rounding_error < 10, - "revenues must go out of the cluster (besides rounding)" - ); - assert_eq!( - earned0 + earned1 + earned2 + burned_fee + manager_fee + rounding_error, - to_distribute, - "all revenues must go to providers" - ); -} - -#[ink::test] -fn bucket_reserve_0_works() { - let contract = setup(); - - assert_eq!( - contract.bucket_list(0, 10, None), - ( - vec![BucketStatus { - bucket_id: 0, - bucket: BucketInStatus { - owner_id: AccountId::default(), - cluster_id: 0, - resource_reserved: 0, - public_availability: false, - resource_consumption_cap: 0, - }, - params: "".to_string(), - writer_ids: vec![AccountId::default()], - reader_ids: vec![], - rent_covered_until_ms: 18446744073709551615, - }], - 1 - ) - ); - - assert_eq!( - contract.cluster_list(0, 10, None), - ( - vec![ClusterInfo { - cluster_id: 0, - cluster: Cluster { - manager_id: AccountId::default(), - v_nodes: vec![], - resource_per_v_node: 0, - resource_used: 0, - revenues: Cash(0), - total_rent: 0, - node_keys: vec![] - }, - params: "".to_string(), - }], - 1 - ) - ); - - assert_eq!( - contract.node_list(0, 10, None), - ( - vec![NodeInfo { - node_key: AccountId::default(), - node: Node { - provider_id: AccountId::default(), - rent_per_month: 0, - free_resource: 0, - status: NodeStatusInCluster::ACTIVE, - node_params: "".to_string(), - } - }], - 1 - ) - ); -} - -#[ink::test] -fn bucket_create_works() { - let ctx = &mut new_cluster(); - let test_bucket = &new_bucket(ctx); - - assert_eq!(test_bucket.bucket_id, 1, "bucket_id must start at 1"); - - // Check the structure of the bucket including the payment flow. - let total_rent = ctx.rent_per_vnode * ctx.vnodes.len() as Balance; - let expect_bucket = Bucket { - owner_id: test_bucket.owner_id, - cluster_id: ctx.cluster_id, - flow: Flow { - from: test_bucket.owner_id, - schedule: Schedule::new(0, total_rent), - }, - resource_reserved: test_bucket.resource, - public_availability: false, - resource_consumption_cap: 0, - }; - - // Check the status of the bucket. - let bucket_status = ctx.contract.bucket_get(test_bucket.bucket_id)?; - assert_eq!( - bucket_status, - BucketStatus { - bucket_id: test_bucket.bucket_id, - bucket: expect_bucket.into(), - params: "{}".to_string(), - writer_ids: vec![test_bucket.owner_id], - reader_ids: vec![], - rent_covered_until_ms: 297600000, // TODO: check this value. - } - ); - - let mut evs = get_events(); - evs.reverse(); // Work with pop(). - evs.truncate(8 - 3 - 2); // Skip 3 NodeCreated and 2 cluster setup events. - - // Create bucket. + // Cluster resource reserved event assert!( - matches!(evs.pop().unwrap(), Event::BucketCreated(ev) if ev == - BucketCreated { bucket_id: test_bucket.bucket_id, owner_id: test_bucket.owner_id }) + matches!(events.pop().unwrap(), Event::ClusterReserveResource(ev) if ev == + ClusterReserveResource { + cluster_id: ctx.cluster_id, + resource: ctx.reserved_resource + }) ); - assert!( - matches!(evs.pop().unwrap(), Event::BucketAllocated(ev) if ev == - BucketAllocated { bucket_id: test_bucket.bucket_id, cluster_id: ctx.cluster_id, resource: test_bucket.resource }) - ); - - // Deposit more. - let net_deposit = 10 * TOKEN; - assert!(matches!(evs.pop().unwrap(), Event::Deposit(ev) if ev == - Deposit { account_id: test_bucket.owner_id, value: net_deposit })); + assert_eq!(events.len(), 0, "All events must be checked"); - assert_eq!(evs.len(), 0, "all events must be checked"); } -#[ink::test] -fn account_deposit_works() { - let account_id = get_accounts().alice; - let mut contract = setup(); - - assert_eq!( - contract.account_get(account_id), - Err(AccountDoesNotExist), - "must not get a non-existent account" - ); - - let deposit = 10 * TOKEN; - let deposit_after_fee = deposit; - - // Deposit some value. - set_caller_value(account_id, deposit); - contract.account_deposit(); - - let account = contract.account_get(account_id)?; - assert_eq!( - account, - Account { - deposit: Cash(deposit_after_fee), - payable_schedule: Schedule::empty(), - bonded: Cash(0), - unbonded_amount: Cash(0), - negative: Cash(0), - unbonded_timestamp: 0, - }, - "must take deposit minus creation fee" - ); - - // Deposit more value. - set_caller_value(account_id, deposit); - contract.account_deposit(); - - let account = contract.account_get(account_id)?; - assert_eq!( - account, - Account { - deposit: Cash(deposit_after_fee + deposit), - payable_schedule: Schedule::empty(), - bonded: Cash(0), - unbonded_amount: Cash(0), - negative: Cash(0), - unbonded_timestamp: 0, - }, - "must take more deposits without creation fee" - ); - - // Check events. - let mut evs = get_events(); - evs.reverse(); // Work with pop(). - - // First deposit event. - assert!(matches!(evs.pop().unwrap(), Event::Deposit(ev) if ev == - Deposit { account_id, value: deposit_after_fee })); - - // Second deposit event. No deposit_contract_fee because the account already exists. - assert!(matches!(evs.pop().unwrap(), Event::Deposit(ev) if ev == - Deposit { account_id, value: deposit })); - - assert_eq!(evs.len(), 0, "all events must be checked"); -} - -#[ink::test] -fn node_change_params_works() { - let ctx = &mut new_cluster(); - - // Change params. - set_caller_value(ctx.provider_id0, CONTRACT_FEE_LIMIT); - ctx.contract - .node_change_params(ctx.node_key0, "new params".to_string()); - - // Check the changed params. - let status = ctx.contract.node_get(ctx.node_key0)?; - assert_eq!(status.node.node_params, "new params"); -} - -#[ink::test] -#[should_panic] -fn node_change_params_only_owner() { - let ctx = &mut new_cluster(); - - // Change params. - set_caller_value(get_accounts().bob, CONTRACT_FEE_LIMIT); - ctx.contract - .node_change_params(ctx.node_key0, "new params".to_string()); - // Panic. -} - -#[ink::test] -fn cluster_change_params_works() { - let ctx = &mut new_cluster(); - - // Change params. - set_caller_value(ctx.manager, CONTRACT_FEE_LIMIT); - ctx.contract - .cluster_change_params(ctx.cluster_id, "new params".to_string()); - - // Check the changed params. - let status = ctx.contract.cluster_get(ctx.cluster_id)?; - assert_eq!(status.params, "new params"); -} - -#[ink::test] -#[should_panic] -fn cluster_change_params_only_owner() { - let ctx = &mut new_cluster(); - - // Change params. - set_caller_value(get_accounts().bob, CONTRACT_FEE_LIMIT); - ctx.contract - .cluster_change_params(ctx.cluster_id, "new params".to_string()); - // Panic. -} - -#[ink::test] -fn bucket_change_params_works() { - let ctx = &mut new_cluster(); - let test_bucket = &new_bucket(ctx); - - // Change params. - set_caller_value(test_bucket.owner_id, CONTRACT_FEE_LIMIT); - ctx.contract - .bucket_change_params(test_bucket.bucket_id, "new params".to_string()); - - // Check the changed params. - let status = ctx.contract.bucket_get(test_bucket.bucket_id)?; - assert_eq!(status.params, "new params"); -} - -#[ink::test] -#[should_panic] -fn bucket_change_params_only_owner() { - let ctx = &mut new_cluster(); - let test_bucket = &new_bucket(ctx); - - // Change params. - set_caller_value(get_accounts().bob, CONTRACT_FEE_LIMIT); - ctx.contract - .bucket_change_params(test_bucket.bucket_id, "new params".to_string()); - // Panic. -} - -#[ink::test] -fn bucket_list_works() { - let mut ddc_bucket = setup(); - let accounts = get_accounts(); - let owner_id1 = accounts.alice; - let owner_id2 = accounts.bob; - let owner_id3 = accounts.charlie; - let cluster_id = 0; - - set_caller_value(owner_id1, CONTRACT_FEE_LIMIT); - let bucket_id1 = ddc_bucket.bucket_create("".to_string(), cluster_id, None); - let bucket_status1 = ddc_bucket.bucket_get(bucket_id1).unwrap(); - - set_caller_value(owner_id2, CONTRACT_FEE_LIMIT); - let bucket_id2 = ddc_bucket.bucket_create("".to_string(), cluster_id, None); - let bucket_status2 = ddc_bucket.bucket_get(bucket_id2)?; - - assert_ne!(bucket_id1, bucket_id2); - let count = 3; - - assert_eq!( - ddc_bucket.bucket_list(1, 100, None), - (vec![bucket_status1.clone(), bucket_status2.clone()], count) - ); - - assert_eq!( - ddc_bucket.bucket_list(1, 2, None), - (vec![bucket_status1.clone(), bucket_status2.clone()], count) - ); - - assert_eq!( - ddc_bucket.bucket_list(1, 1, None), - ( - vec![bucket_status1.clone() /*, bucket_status2.clone()*/], - count - ) - ); - assert_eq!( - ddc_bucket.bucket_list(2, 1, None), - ( - vec![/*bucket_status1.clone(),*/ bucket_status2.clone()], - count - ) - ); - - assert_eq!(ddc_bucket.bucket_list(count, 20, None), (vec![], count)); - - // Filter by owner. - assert_eq!( - ddc_bucket.bucket_list(1, 100, Some(owner_id1)), - ( - vec![bucket_status1.clone() /*, bucket_status2.clone()*/], - count - ) - ); - - assert_eq!( - ddc_bucket.bucket_list(1, 100, Some(owner_id2)), - ( - vec![/*bucket_status1.clone(),*/ bucket_status2.clone()], - count - ) - ); - - assert_eq!( - ddc_bucket.bucket_list(1, 100, Some(owner_id3)), - (vec![], count) - ); -} - -#[ink::test] -fn bucket_set_availability_works() { - let ctx = &mut new_cluster(); - let test_bucket = &new_bucket(ctx); - let status = ctx.contract.bucket_get(test_bucket.bucket_id)?; - assert_eq!(status.bucket.public_availability, false); - - // Set public availability - ctx.contract - .bucket_set_availability(test_bucket.bucket_id, true); - - // Check the last event. - let ev = get_events().pop().unwrap(); - assert!(matches!(ev, Event::BucketAvailabilityUpdated(ev) if ev == - BucketAvailabilityUpdated { bucket_id: test_bucket.bucket_id, public_availability: true })); - - // Check the changed params. - let status = ctx.contract.bucket_get(test_bucket.bucket_id)?; - assert_eq!(status.bucket.public_availability, true); -} - -#[ink::test] -fn node_list_works() { - let mut ddc_bucket = setup(); - let accounts = get_accounts(); - let owner_id1 = accounts.alice; - let owner_id2 = accounts.bob; - let owner_id3 = accounts.charlie; - let rent_per_month: Balance = 10 * TOKEN; - - // Create two Nodes. - let node_params1 = "{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"; - let capacity = 100; - set_caller_value(owner_id1, CONTRACT_FEE_LIMIT); - let node_key1 = ddc_bucket.node_create( - AccountId::from([0x0b; 32]), - rent_per_month, - node_params1.to_string(), - capacity, - NodeStatusInCluster::ADDING, - ); - - let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; - set_caller_value(owner_id2, CONTRACT_FEE_LIMIT); - let node_key2 = ddc_bucket.node_create( - AccountId::from([0x0c; 32]), - rent_per_month, - node_params2.to_string(), - capacity, - NodeStatusInCluster::ADDING, - ); - - let node_status = ddc_bucket.node_get(AccountId::from([0x0b; 32])).unwrap(); - assert_eq!(owner_id1, node_status.node.provider_id.clone()); - - assert_ne!(node_key1, node_key2); - let count = 3; - - let node1 = NodeInfo { - node_key: node_key1, - node: Node { - provider_id: owner_id1, - rent_per_month, - free_resource: capacity, - status: NodeStatusInCluster::ADDING, - node_params: node_params1.to_string(), - }, - }; - - let node2 = NodeInfo { - node_key: node_key2, - node: Node { - provider_id: owner_id2, - rent_per_month, - free_resource: capacity, - status: NodeStatusInCluster::ADDING, - node_params: node_params2.to_string(), - }, - }; - - assert_eq!( - ddc_bucket.node_list(1, 100, None), - (vec![node1.clone(), node2.clone()], count) - ); - - assert_eq!( - ddc_bucket.node_list(1, 2, None), - (vec![node1.clone(), node2.clone()], count) - ); - - assert_eq!( - ddc_bucket.node_list(1, 1, None), - (vec![node1.clone() /*, node2.clone()*/], count) - ); - - assert_eq!( - ddc_bucket.node_list(2, 1, None), - (vec![/*node1.clone(),*/ node2.clone()], count) - ); - - assert_eq!(ddc_bucket.node_list(21, 20, None), (vec![], count)); - - // Filter by owner. - assert_eq!( - ddc_bucket.node_list(1, 100, Some(owner_id1)), - (vec![node1.clone() /*, node2.clone()*/], count) - ); - - assert_eq!( - ddc_bucket.node_list(1, 100, Some(owner_id2)), - (vec![/*node1.clone(),*/ node2.clone()], count) - ); - - assert_eq!( - ddc_bucket.node_list(1, 100, Some(owner_id3)), - (vec![], count) - ); -} +// #[ink::test] +// fn cluster_replace_node_only_manager() { +// let mut ctx = new_cluster(); +// let not_manager = get_accounts().alice; +// set_caller_value(not_manager, 0); + +// // Reassign a vnode from node1 to node2. +// assert_eq!( +// ctx.contract +// .message_cluster_replace_node( +// ctx.cluster_id, +// vec![1, 2, 3], +// ctx.node_key2 +// ), +// Err(OnlyClusterManager) +// ); +// } + +// #[ink::test] +// fn cluster_replace_node_only_trusted_manager() { +// let mut ctx = new_cluster(); + +// // The provider stops trusting the manager_id. +// set_caller(ctx.provider_id2); +// ctx.contract.node_distrust_manager(ctx.manager_id); + +// set_caller_value(ctx.manager_id, 0); + +// // The manager_id cannot use nodes of the provider. +// assert_eq!( +// ctx.contract +// .message_cluster_replace_node( +// ctx.cluster_id, +// vec![1, 2, 3], +// ctx.node_key2 +// ), +// Err(OnlyTrustedClusterManager) +// ); +// } + +// #[ink::test] +// fn cluster_replace_node_works() { +// let mut ctx = new_cluster(); +// set_caller_value(ctx.manager_id, 0); + +// // Reassign a vnode from node1 to node2. +// ctx.contract +// .cluster_replace_node(ctx.cluster_id, vec![1, 3], ctx.node_key2); + +// // Check the last event. +// let ev = get_events().pop().unwrap(); +// assert!(matches!(ev, Event::ClusterNodeReplaced(ev) if ev == +// ClusterNodeReplaced { cluster_id: ctx.cluster_id, node_key: ctx.node_key2 })); + +// let vnodes_for_replaced = vec![2]; +// let vnodes_for_second_node = vec![4, 5, 6]; +// let vnodes_for_third_node = vec![7, 8, 9]; +// let vnodes_for_third_dup = vec![1, 3]; + +// let vnodes = vec![ +// vnodes_for_replaced, +// vnodes_for_second_node, +// vnodes_for_third_node, +// vnodes_for_third_dup, +// ]; + +// // Check the changed state of the cluster. +// let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; +// println!("cluster.v_nodes: {:?}", cluster.v_nodes.clone()); +// println!("cluster.node_keys: {:?}", cluster.node_keys.clone()); +// assert_eq!(&cluster.v_nodes, &vnodes, "a vnode must be replaced"); + +// // Check the changed state of the nodes. +// let expected_resources = [ +// (ctx.node_key0, 100 - 10), +// (ctx.node_key1, 100 - 10 - 10 - 10), +// (ctx.node_key2, 100 - 10 - 10 - 10 - 10 - 10), +// ]; + +// for (node_key, available) in expected_resources { +// let node_status = ctx.contract.node_get(node_key).unwrap(); +// assert_eq!( +// node_status.node.free_resource, available, +// "resources must have shifted between nodes" +// ); +// } +// } + +// #[ink::test] +// fn cluster_reserve_works() { +// let mut ctx = new_cluster(); +// set_caller_value(ctx.manager_id, 0); + +// // Reserve more resources. +// ctx.contract.cluster_reserve_resource(ctx.cluster_id, 5); + +// // Check the last event. +// let ev = get_events().pop().unwrap(); +// assert!(matches!(ev, Event::ClusterReserveResource(ev) if ev == +// ClusterReserveResource { cluster_id: ctx.cluster_id, resource: 5 })); + +// // Check the changed state of the cluster. +// let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; +// assert_eq!(cluster.resource_per_v_node, 10 + 5); + +// // Check the changed state of the nodes. +// let expected_resources = [ +// (ctx.node_key0, 100 - 40 - 5), +// (ctx.node_key1, 100 - 40 - 5), +// (ctx.node_key2, 100 - 40 - 5), +// ]; +// for (node_id, available) in expected_resources { +// assert_eq!( +// ctx.contract.node_get(node_id)?.node.free_resource, +// available, +// "more resources must be reserved from the nodes" +// ); +// } +// } + +// #[ink::test] +// fn cluster_management_validation_works() { +// let mut ctx = new_cluster(); + +// let not_manager = ctx.provider_id0; +// set_caller_value(not_manager, 0); + +// assert_eq!( +// ctx.contract +// .message_cluster_replace_node( +// ctx.cluster_id, +// vec![1, 2, 3], +// AccountId::from([0x0a; 32]) +// ), +// Err(OnlyClusterManager), +// "only the manager_id can modify the cluster" +// ); + +// set_caller_value(ctx.manager_id, 0); + +// let bad_node_id = AccountId::from([0x0d; 32]); +// assert_eq!( +// ctx.contract +// .message_cluster_replace_node( +// ctx.cluster_id, +// vec![1, 2, 3], +// bad_node_id +// ), +// Err(NodeDoesNotExist), +// "cluster replacement node must exist" +// ); + +// assert_eq!( +// ctx.contract +// .message_cluster_create(vec![vec![1, 2, 3]], vec![bad_node_id], vec![1, 2, 3], "".to_string()), +// Err(NodeDoesNotExist), +// "cluster initial nodes must exist" +// ); +// } + +// // #[ink::test] +// // fn cdn_cluster_gas_converter_works() { +// // println!("Creating new cdn cluster"); + +// // let mut ctx = new_cluster_cdn(); + +// // println!("Got cdn cluster back"); +// // // The provider stops trusting the manager_id. +// // println!("Cdn cluster id is {}", ctx.cluster_id); +// // set_caller(ctx.manager_id); +// // ctx.contract.cdn_set_rate(ctx.cluster_id, 3_750_000_000); +// // set_caller(ctx.provider_id0); +// // let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); + +// // let usd_per_cere = TOKEN / 100; +// // set_caller(ctx.provider_id0); +// // ctx.contract.account_set_usd_per_cere(usd_per_cere); + +// // let usd_amount = ctx.contract.account_get_usd_per_cere(); +// // println!("Current usd amount is {}", usd_amount); + +// // println!("The current rate is {}", rate); + +// // let usd_per_kb = rate / KB_PER_GB; +// // println!("The current rate per kb {}", usd_per_kb); + +// // let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); +// // println!("The current cere rate per kb {}", cere_per_kb); +// // } + +// // #[ink::test] +// // fn cdn_cluster_payment_works() { +// // println!("Creating new cdn cluster"); + +// // let mut ctx = new_cluster_cdn(); + +// // println!("Got cdn cluster back"); +// // // The provider stops trusting the manager_id. +// // println!("Cdn cluster id is {}", ctx.cluster_id); +// // set_caller(ctx.provider_id0); +// // let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); + +// // let usd_per_cere = TOKEN / 100; +// // set_caller(ctx.provider_id0); +// // ctx.contract.account_set_usd_per_cere(usd_per_cere); + +// // let usd_amount = ctx.contract.account_get_usd_per_cere(); +// // println!("Current usd amount is {}", usd_amount); + +// // println!("The current rate is {}", rate); + +// // let usd_per_kb = rate / KB_PER_GB; +// // println!("The current rate per kb {}", usd_per_kb); + +// // let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); +// // println!("The current cere rate per kb {}", cere_per_kb); + +// // set_caller_value(ctx.provider_id0, 10 * TOKEN); +// // ctx.contract.account_deposit(); + +// // set_caller(ctx.provider_id0); +// // ctx.contract.account_bond(5 * TOKEN); + +// // set_caller(ctx.provider_id0); +// // ctx.contract.set_fee_bp(1_000); + +// // let mut account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); +// // println!("{:?}", account); + +// // ctx.contract.cdn_cluster_put_revenue( +// // ctx.cluster_id, +// // vec![(ctx.provider_id0, 1000), (ctx.provider_id0, 541643)], +// // vec![(ctx.node_key0, 1000), (ctx.node_key1, 541643)], +// // vec![], +// // 5, +// // ); +// // account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); +// // println!("{:?}", account); + +// // let cdn_cluster_list_one = ctx.contract.cdn_cluster_list(0, 10, None); +// // print!("Cluster list one {:?}", cdn_cluster_list_one); +// // let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); +// // let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); + +// // println!("Node 1 {:?}", node0); +// // println!("Node 2 {:?}", node1); +// // // let cdn_cluster0 = ctx.contract.cdn_clusters.get(ctx.cluster_id); +// // // print!("{:?}", cdn_cluster0); +// // // let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); +// // // print!("{:?}", cdn_cluster0); +// // // print!("{:?}", cdn_cluster_list); + +// // let validated_commit_node0 = ctx.contract.get_validated_commit(ctx.node_key0); +// // print!("Validated commit {:?}", validated_commit_node0); + +// // let fee = ctx.contract.get_fee_bp(); +// // print!("Protocol fee in basis points {:?}", fee); + +// // let protocol_revenues = ctx.contract.get_protocol_revenues(); +// // print!("Protocol revenues are {:?}", protocol_revenues); + +// // set_caller(ctx.provider_id0); +// // ctx.contract.cdn_cluster_distribute_revenues(0); + +// // let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); +// // let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); +// // println!("{:?}", node0); +// // println!("{:?}", node1); + +// // let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); +// // print!("{:?}", cdn_cluster_list); + +// // account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); +// // // let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); +// // // let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); +// // println!("{:?}", account); +// // // let account1 = ctx.contract.accounts.get(&ctx.provider_id1).unwrap(); +// // // println!("{:?}", account1); +// // // let account_balance = ink_env::balance(&ctx.provider_id0); +// // // println!("{:?}", account_balance); +// // } + +// fn bucket_settle_payment(ctx: &mut TestCluster, test_bucket: &TestBucket) { +// // Go to the future when some revenues are due. +// advance_block::(); +// // Pay the due thus far. +// set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); +// ctx.contract.bucket_settle_payment(test_bucket.bucket_id); +// } + +// #[ink::test] +// fn bucket_pays_cluster() { +// let ctx = &mut new_cluster(); +// let test_bucket = &new_bucket(ctx); +// do_bucket_pays_cluster(ctx, test_bucket, 1).unwrap(); +// } + +// #[ink::test] +// fn bucket_pays_cluster_at_new_rate() { +// let ctx = &mut new_cluster(); +// let test_bucket = &new_bucket(ctx); + +// // Set up an exchange rate manager_id. +// set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); +// ctx.contract +// .admin_grant_permission(admin_id(), Permission::SetExchangeRate); + +// // Change the currency exchange rate. +// let usd_per_cere = 2; +// set_caller(admin_id()); +// ctx.contract.account_set_usd_per_cere(usd_per_cere * TOKEN); + +// do_bucket_pays_cluster(ctx, test_bucket, usd_per_cere).unwrap(); +// } + +// fn do_bucket_pays_cluster( +// ctx: &mut TestCluster, +// test_bucket: &TestBucket, +// usd_per_cere: Balance, +// ) -> Result<()> { +// let expected_rent = ctx.rent_per_v_node * ctx.vnodes.len() as Balance; + +// // Check the state before payment. +// let before = ctx +// .contract +// .account_get(test_bucket.owner_id)? +// .deposit +// .peek(); +// let bucket = ctx.contract.bucket_get(test_bucket.bucket_id)?.bucket; +// assert_eq!(bucket.owner_id, test_bucket.owner_id); +// /* TODO: Not testable at the moment, see struct BucketInStatus. +// assert_eq!(bucket.flow, +// Flow { +// from: test_bucket.owner_id, +// schedule: Schedule::new(0, expected_rent), +// }); +// */ +// let timestamp_before = block_timestamp::(); +// bucket_settle_payment(ctx, &test_bucket); +// let timestamp_after = block_timestamp::(); + +// // Check the last event. +// let ev = get_events().pop().unwrap(); +// assert!(matches!(ev, Event::BucketSettlePayment(ev) if ev == +// BucketSettlePayment { bucket_id: test_bucket.bucket_id, cluster_id: ctx.cluster_id })); + +// // Check the state after payment. +// let after = ctx +// .contract +// .account_get(test_bucket.owner_id)? +// .deposit +// .peek(); +// let spent = before - after; +// /* TODO: Not testable at the moment, see struct BucketInStatus. +// let bucket = ctx.contract.bucket_get(test_bucket.bucket_id)?.bucket; +// assert_eq!(bucket.flow, +// Flow { +// from: test_bucket.owner_id, +// schedule: Schedule::new(BLOCK_TIME, expected_rent), +// }); +// */ +// let timespan = timestamp_after - timestamp_before; +// let expect_revenues_usd = expected_rent * timespan as u128 / MS_PER_MONTH as u128; +// let expect_revenues = expect_revenues_usd / usd_per_cere; +// assert!(expect_revenues > 0); +// assert_eq!( +// expect_revenues, spent, +// "revenues must come from the bucket owner" +// ); + +// let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; +// assert_eq!( +// cluster.revenues.peek(), +// expect_revenues, +// "must get revenues into the cluster" +// ); + +// Ok(()) +// } + +// #[ink::test] +// fn cluster_add_node() { +// let ctx = &mut new_cluster(); + +// let new_provider_id = get_accounts().frank; +// set_balance(new_provider_id, 1000 * TOKEN); + +// let rent_per_month = 100; +// let node_params = "new_node"; +// let capacity = 1000; +// let status = NodeStatusInCluster::ACTIVE; + +// set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); +// let new_node_id = ctx.contract.node_create( +// AccountId::from([0x0d; 32]), +// rent_per_month, +// node_params.to_string(), +// capacity, +// status, +// ); + +// set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); +// ctx.contract.node_trust_manager(ctx.manager_id); +// assert!( +// matches!(get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == +// PermissionGranted { account_id: ctx.manager_id, permission: Permission::ClusterManagerTrustedBy(new_provider_id) }) +// ); + +// let mut node_keys = Vec::::new(); +// node_keys.push(ctx.node_key0); +// node_keys.push(ctx.node_key1); +// node_keys.push(ctx.node_key2); +// node_keys.push(new_node_id); + +// let mut v_nodes = ctx.vnodes_wrapper.clone(); +// v_nodes.push(vec![10, 11, 12]); + +// set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); +// ctx.contract +// .cluster_add_node(ctx.cluster_id, node_keys.clone(), v_nodes.clone()); + +// let cluster_status = ctx.contract.cluster_get(ctx.cluster_id).unwrap(); +// assert!(matches!(cluster_status.clone().cluster.node_keys.len(), 4)); +// assert!(matches!(cluster_status.clone().cluster.v_nodes.len(), 4)); +// } + +// #[ink::test] +// fn cluster_pays_providers() { +// let ctx = &mut new_cluster(); +// let test_bucket = &new_bucket(ctx); +// bucket_settle_payment(ctx, &test_bucket); + +// // Get state before the distribution. +// let to_distribute = ctx +// .contract +// .cluster_get(ctx.cluster_id)? +// .cluster +// .revenues +// .peek(); +// let before0 = balance_of(ctx.provider_id0); +// let before1 = balance_of(ctx.provider_id1); +// let before2 = balance_of(ctx.provider_id2); +// let before_mgmt = balance_of(ctx.manager_id); + +// let skip_events = get_events::().len(); + +// // Set a network fee. +// let network_fee_bp = 100; // 1% +// let cluster_management_fee_bp = 200; // 2% +// set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); +// ctx.contract.admin_set_fee_config(FeeConfig { +// network_fee_bp, +// network_fee_destination: AccountId::default(), +// cluster_management_fee_bp, +// }); + +// let burned_fee = to_distribute * network_fee_bp / 10_000; +// let manager_fee = (to_distribute - burned_fee) * cluster_management_fee_bp / 10_000; +// let provider_fee = (to_distribute - burned_fee - manager_fee) / 3; + +// // Distribute the revenues of the cluster to providers. +// ctx.contract.cluster_distribute_revenues(ctx.cluster_id); + +// // Check the last events. +// let mut events = get_events(); +// events.reverse(); // Work with pop(). +// events.truncate(events.len() - skip_events); +// let expected_recipients = vec![ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; + +// for provider_id in expected_recipients { +// assert!( +// matches!(events.pop().unwrap(), Event::ClusterDistributeRevenues(ev) if ev == +// ClusterDistributeRevenues { cluster_id: ctx.cluster_id, provider_id }) +// ); +// } + +// assert_eq!(events.len(), 0, "all events must be checked"); + +// // Get state after the distribution. +// let rounding_error = ctx +// .contract +// .cluster_get(ctx.cluster_id)? +// .cluster +// .revenues +// .peek(); +// let earned0 = balance_of(ctx.provider_id0) - before0; +// let earned1 = balance_of(ctx.provider_id1) - before1; +// let earned2 = balance_of(ctx.provider_id2) - before2; +// let earned_mgmt = balance_of(ctx.manager_id) - before_mgmt; + +// assert!(provider_fee > 0, "provider must earn something"); +// assert_eq!( +// earned0, provider_fee, +// "providers must earn the correct amount" +// ); +// assert_eq!( +// earned1, provider_fee, +// "providers must earn the correct amount" +// ); +// assert_eq!( +// earned2, provider_fee, +// "providers must earn the correct amount" +// ); + +// assert!(burned_fee > 0, "the network must earn something"); +// assert!(manager_fee > 0, "the manager_id must earn something"); +// assert_eq!( +// earned_mgmt, manager_fee, +// "the manager_id must earn the correct amount" +// ); + +// assert!(to_distribute > 0); +// assert!( +// rounding_error < 10, +// "revenues must go out of the cluster (besides rounding)" +// ); +// assert_eq!( +// earned0 + earned1 + earned2 + burned_fee + manager_fee + rounding_error, +// to_distribute, +// "all revenues must go to providers" +// ); +// } + +// #[ink::test] +// fn bucket_reserve_0_works() { +// let contract = setup(); + +// assert_eq!( +// contract.bucket_list(0, 10, None), +// ( +// vec![BucketStatus { +// bucket_id: 0, +// bucket: BucketInStatus { +// owner_id: AccountId::default(), +// cluster_id: 0, +// resource_reserved: 0, +// public_availability: false, +// resource_consumption_cap: 0, +// }, +// params: "".to_string(), +// writer_ids: vec![AccountId::default()], +// reader_ids: vec![], +// rent_covered_until_ms: 18446744073709551615, +// }], +// 1 +// ) +// ); + +// assert_eq!( +// contract.cluster_list(0, 10, None), +// ( +// vec![ClusterInfo { +// cluster_id: 0, +// cluster: Cluster { +// manager_id: AccountId::default(), +// v_nodes: vec![], +// resource_per_v_node: 0, +// resource_used: 0, +// revenues: Cash(0), +// total_rent: 0, +// node_keys: vec![] +// }, +// params: "".to_string(), +// }], +// 1 +// ) +// ); + +// assert_eq!( +// contract.node_list(0, 10, None), +// ( +// vec![NodeInfo { +// node_key: AccountId::default(), +// node: Node { +// provider_id: AccountId::default(), +// rent_per_month: 0, +// free_resource: 0, +// status: NodeStatusInCluster::ACTIVE, +// node_params: "".to_string(), +// } +// }], +// 1 +// ) +// ); +// } + +// #[ink::test] +// fn bucket_create_works() { +// let ctx = &mut new_cluster(); +// let test_bucket = &new_bucket(ctx); + +// assert_eq!(test_bucket.bucket_id, 1, "bucket_id must start at 1"); + +// // Check the structure of the bucket including the payment flow. +// let total_rent = ctx.rent_per_v_node * ctx.vnodes.len() as Balance; +// let expect_bucket = Bucket { +// owner_id: test_bucket.owner_id, +// cluster_id: ctx.cluster_id, +// flow: Flow { +// from: test_bucket.owner_id, +// schedule: Schedule::new(0, total_rent), +// }, +// resource_reserved: test_bucket.resource, +// public_availability: false, +// resource_consumption_cap: 0, +// }; + +// // Check the status of the bucket. +// let bucket_status = ctx.contract.bucket_get(test_bucket.bucket_id)?; +// assert_eq!( +// bucket_status, +// BucketStatus { +// bucket_id: test_bucket.bucket_id, +// bucket: expect_bucket.into(), +// params: "{}".to_string(), +// writer_ids: vec![test_bucket.owner_id], +// reader_ids: vec![], +// rent_covered_until_ms: 297600000, // TODO: check this value. +// } +// ); + +// let mut events = get_events(); +// events.reverse(); // Work with pop(). +// events.truncate(8 - 3 - 2); // Skip 3 NodeCreated and 2 cluster setup events. + +// // Create bucket. +// assert!( +// matches!(events.pop().unwrap(), Event::BucketCreated(ev) if ev == +// BucketCreated { bucket_id: test_bucket.bucket_id, owner_id: test_bucket.owner_id }) +// ); + +// assert!( +// matches!(events.pop().unwrap(), Event::BucketAllocated(ev) if ev == +// BucketAllocated { bucket_id: test_bucket.bucket_id, cluster_id: ctx.cluster_id, resource: test_bucket.resource }) +// ); + +// // Deposit more. +// let net_deposit = 10 * TOKEN; +// assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == +// Deposit { account_id: test_bucket.owner_id, value: net_deposit })); + +// assert_eq!(events.len(), 0, "all events must be checked"); +// } + +// #[ink::test] +// fn account_deposit_works() { +// let account_id = get_accounts().alice; +// let mut contract = setup(); + +// assert_eq!( +// contract.account_get(account_id), +// Err(AccountDoesNotExist), +// "must not get a non-existent account" +// ); + +// let deposit = 10 * TOKEN; +// let deposit_after_fee = deposit; + +// // Deposit some value. +// set_caller_value(account_id, deposit); +// contract.account_deposit(); + +// let account = contract.account_get(account_id)?; +// assert_eq!( +// account, +// Account { +// deposit: Cash(deposit_after_fee), +// payable_schedule: Schedule::empty(), +// bonded: Cash(0), +// unbonded_amount: Cash(0), +// negative: Cash(0), +// unbonded_timestamp: 0, +// }, +// "must take deposit minus creation fee" +// ); + +// // Deposit more value. +// set_caller_value(account_id, deposit); +// contract.account_deposit(); + +// let account = contract.account_get(account_id)?; +// assert_eq!( +// account, +// Account { +// deposit: Cash(deposit_after_fee + deposit), +// payable_schedule: Schedule::empty(), +// bonded: Cash(0), +// unbonded_amount: Cash(0), +// negative: Cash(0), +// unbonded_timestamp: 0, +// }, +// "must take more deposits without creation fee" +// ); + +// // Check events. +// let mut events = get_events(); +// events.reverse(); // Work with pop(). + +// // First deposit event. +// assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == +// Deposit { account_id, value: deposit_after_fee })); + +// // Second deposit event. No deposit_contract_fee because the account already exists. +// assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == +// Deposit { account_id, value: deposit })); + +// assert_eq!(events.len(), 0, "all events must be checked"); +// } + +// #[ink::test] +// fn node_change_params_works() { +// let ctx = &mut new_cluster(); + +// // Change params. +// set_caller_value(ctx.provider_id0, CONTRACT_FEE_LIMIT); +// ctx.contract +// .node_change_params(ctx.node_key0, "new params".to_string()); + +// // Check the changed params. +// let status = ctx.contract.node_get(ctx.node_key0)?; +// assert_eq!(status.node.node_params, "new params"); +// } + +// #[ink::test] +// #[should_panic] +// fn node_change_params_only_owner() { +// let ctx = &mut new_cluster(); + +// // Change params. +// set_caller_value(get_accounts().bob, CONTRACT_FEE_LIMIT); +// ctx.contract +// .node_change_params(ctx.node_key0, "new params".to_string()); +// // Panic. +// } + +// #[ink::test] +// fn cluster_change_params_works() { +// let ctx = &mut new_cluster(); + +// // Change params. +// set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); +// ctx.contract +// .cluster_change_params(ctx.cluster_id, "new params".to_string()); + +// // Check the changed params. +// let status = ctx.contract.cluster_get(ctx.cluster_id)?; +// assert_eq!(status.params, "new params"); +// } + +// #[ink::test] +// #[should_panic] +// fn cluster_change_params_only_owner() { +// let ctx = &mut new_cluster(); + +// // Change params. +// set_caller_value(get_accounts().bob, CONTRACT_FEE_LIMIT); +// ctx.contract +// .cluster_change_params(ctx.cluster_id, "new params".to_string()); +// // Panic. +// } + +// #[ink::test] +// fn bucket_change_params_works() { +// let ctx = &mut new_cluster(); +// let test_bucket = &new_bucket(ctx); + +// // Change params. +// set_caller_value(test_bucket.owner_id, CONTRACT_FEE_LIMIT); +// ctx.contract +// .bucket_change_params(test_bucket.bucket_id, "new params".to_string()); + +// // Check the changed params. +// let status = ctx.contract.bucket_get(test_bucket.bucket_id)?; +// assert_eq!(status.params, "new params"); +// } + +// #[ink::test] +// #[should_panic] +// fn bucket_change_params_only_owner() { +// let ctx = &mut new_cluster(); +// let test_bucket = &new_bucket(ctx); + +// // Change params. +// set_caller_value(get_accounts().bob, CONTRACT_FEE_LIMIT); +// ctx.contract +// .bucket_change_params(test_bucket.bucket_id, "new params".to_string()); +// // Panic. +// } + +// #[ink::test] +// fn bucket_list_works() { +// let mut ddc_bucket = setup(); +// let accounts = get_accounts(); +// let owner_id1 = accounts.alice; +// let owner_id2 = accounts.bob; +// let owner_id3 = accounts.charlie; +// let cluster_id = 0; + +// set_caller_value(owner_id1, CONTRACT_FEE_LIMIT); +// let bucket_id1 = ddc_bucket.bucket_create("".to_string(), cluster_id, None); +// let bucket_status1 = ddc_bucket.bucket_get(bucket_id1).unwrap(); + +// set_caller_value(owner_id2, CONTRACT_FEE_LIMIT); +// let bucket_id2 = ddc_bucket.bucket_create("".to_string(), cluster_id, None); +// let bucket_status2 = ddc_bucket.bucket_get(bucket_id2)?; + +// assert_ne!(bucket_id1, bucket_id2); +// let count = 3; + +// assert_eq!( +// ddc_bucket.bucket_list(1, 100, None), +// (vec![bucket_status1.clone(), bucket_status2.clone()], count) +// ); + +// assert_eq!( +// ddc_bucket.bucket_list(1, 2, None), +// (vec![bucket_status1.clone(), bucket_status2.clone()], count) +// ); + +// assert_eq!( +// ddc_bucket.bucket_list(1, 1, None), +// ( +// vec![bucket_status1.clone() /*, bucket_status2.clone()*/], +// count +// ) +// ); +// assert_eq!( +// ddc_bucket.bucket_list(2, 1, None), +// ( +// vec![/*bucket_status1.clone(),*/ bucket_status2.clone()], +// count +// ) +// ); + +// assert_eq!(ddc_bucket.bucket_list(count, 20, None), (vec![], count)); + +// // Filter by owner. +// assert_eq!( +// ddc_bucket.bucket_list(1, 100, Some(owner_id1)), +// ( +// vec![bucket_status1.clone() /*, bucket_status2.clone()*/], +// count +// ) +// ); + +// assert_eq!( +// ddc_bucket.bucket_list(1, 100, Some(owner_id2)), +// ( +// vec![/*bucket_status1.clone(),*/ bucket_status2.clone()], +// count +// ) +// ); + +// assert_eq!( +// ddc_bucket.bucket_list(1, 100, Some(owner_id3)), +// (vec![], count) +// ); +// } + +// #[ink::test] +// fn bucket_set_availability_works() { +// let ctx = &mut new_cluster(); +// let test_bucket = &new_bucket(ctx); +// let status = ctx.contract.bucket_get(test_bucket.bucket_id)?; +// assert_eq!(status.bucket.public_availability, false); + +// // Set public availability +// ctx.contract +// .bucket_set_availability(test_bucket.bucket_id, true); + +// // Check the last event. +// let ev = get_events().pop().unwrap(); +// assert!(matches!(ev, Event::BucketAvailabilityUpdated(ev) if ev == +// BucketAvailabilityUpdated { bucket_id: test_bucket.bucket_id, public_availability: true })); + +// // Check the changed params. +// let status = ctx.contract.bucket_get(test_bucket.bucket_id)?; +// assert_eq!(status.bucket.public_availability, true); +// } + +// #[ink::test] +// fn node_list_works() { +// let mut ddc_bucket = setup(); +// let accounts = get_accounts(); +// let owner_id1 = accounts.alice; +// let owner_id2 = accounts.bob; +// let owner_id3 = accounts.charlie; +// let rent_per_month: Balance = 10 * TOKEN; + +// // Create two Nodes. +// let node_params1 = "{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"; +// let capacity = 100; +// set_caller_value(owner_id1, CONTRACT_FEE_LIMIT); +// let node_key1 = ddc_bucket.node_create( +// AccountId::from([0x0b; 32]), +// rent_per_month, +// node_params1.to_string(), +// capacity, +// NodeStatusInCluster::ADDING, +// ); + +// let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; +// set_caller_value(owner_id2, CONTRACT_FEE_LIMIT); +// let node_key2 = ddc_bucket.node_create( +// AccountId::from([0x0c; 32]), +// rent_per_month, +// node_params2.to_string(), +// capacity, +// NodeStatusInCluster::ADDING, +// ); + +// let node_status = ddc_bucket.node_get(AccountId::from([0x0b; 32])).unwrap(); +// assert_eq!(owner_id1, node_status.node.provider_id.clone()); + +// assert_ne!(node_key1, node_key2); +// let count = 3; + +// let node1 = NodeInfo { +// node_key: node_key1, +// node: Node { +// provider_id: owner_id1, +// rent_per_month, +// free_resource: capacity, +// status: NodeStatusInCluster::ADDING, +// node_params: node_params1.to_string(), +// }, +// }; + +// let node2 = NodeInfo { +// node_key: node_key2, +// node: Node { +// provider_id: owner_id2, +// rent_per_month, +// free_resource: capacity, +// status: NodeStatusInCluster::ADDING, +// node_params: node_params2.to_string(), +// }, +// }; + +// assert_eq!( +// ddc_bucket.node_list(1, 100, None), +// (vec![node1.clone(), node2.clone()], count) +// ); + +// assert_eq!( +// ddc_bucket.node_list(1, 2, None), +// (vec![node1.clone(), node2.clone()], count) +// ); + +// assert_eq!( +// ddc_bucket.node_list(1, 1, None), +// (vec![node1.clone() /*, node2.clone()*/], count) +// ); + +// assert_eq!( +// ddc_bucket.node_list(2, 1, None), +// (vec![/*node1.clone(),*/ node2.clone()], count) +// ); + +// assert_eq!(ddc_bucket.node_list(21, 20, None), (vec![], count)); + +// // Filter by owner. +// assert_eq!( +// ddc_bucket.node_list(1, 100, Some(owner_id1)), +// (vec![node1.clone() /*, node2.clone()*/], count) +// ); + +// assert_eq!( +// ddc_bucket.node_list(1, 100, Some(owner_id2)), +// (vec![/*node1.clone(),*/ node2.clone()], count) +// ); + +// assert_eq!( +// ddc_bucket.node_list(1, 100, Some(owner_id3)), +// (vec![], count) +// ); +// } diff --git a/bucket/ddc_bucket/tests/test_currency.rs b/bucket/ddc_bucket/tests/test_currency.rs index e64c5fef..a7319927 100644 --- a/bucket/ddc_bucket/tests/test_currency.rs +++ b/bucket/ddc_bucket/tests/test_currency.rs @@ -1,52 +1,52 @@ -use ink_lang as ink; - -use crate::ddc_bucket::*; - -use super::env_utils::*; - -fn setup() -> DdcBucket { - set_caller(admin_id()); - set_callee(contract_id()); - let mut contract = DdcBucket::new(); - set_balance(contract_id(), CONTRACT_FEE_LIMIT); - contract.admin_grant_permission(admin_id(), Permission::SetExchangeRate); - contract -} - -#[ink::test] -fn currency_conversion_init_works() { - let contract = setup(); - let usd_amount = contract.account_get_usd_per_cere(); - println!("{}", usd_amount); - assert_eq!( - contract.account_get_usd_per_cere(), - 1 * TOKEN, - "conversion rate must be 1 initially" - ); -} - -#[ink::test] -fn currency_conversion_set_rate_works() { - let mut contract = setup(); - let usd_per_cere = TOKEN / 10; - println!("{}", usd_per_cere); - - set_caller(admin_id()); - contract.account_set_usd_per_cere(usd_per_cere); - - assert_eq!( - contract.account_get_usd_per_cere(), - usd_per_cere, - "conversion rate must be changed" - ); -} - -#[ink::test] -#[should_panic] -fn currency_conversion_set_rate_only_admin() { - let mut contract = setup(); - let not_admin = get_accounts().bob; - - set_caller(not_admin); - contract.account_set_usd_per_cere(9); -} +// use ink_lang as ink; + +// use crate::ddc_bucket::*; + +// use super::env_utils::*; + +// fn setup() -> DdcBucket { +// set_caller(admin_id()); +// set_callee(contract_id()); +// let mut contract = DdcBucket::new(); +// set_balance(contract_id(), CONTRACT_FEE_LIMIT); +// contract.admin_grant_permission(admin_id(), Permission::SetExchangeRate); +// contract +// } + +// #[ink::test] +// fn currency_conversion_init_works() { +// let contract = setup(); +// let usd_amount = contract.account_get_usd_per_cere(); +// println!("{}", usd_amount); +// assert_eq!( +// contract.account_get_usd_per_cere(), +// 1 * TOKEN, +// "conversion rate must be 1 initially" +// ); +// } + +// #[ink::test] +// fn currency_conversion_set_rate_works() { +// let mut contract = setup(); +// let usd_per_cere = TOKEN / 10; +// println!("{}", usd_per_cere); + +// set_caller(admin_id()); +// contract.account_set_usd_per_cere(usd_per_cere); + +// assert_eq!( +// contract.account_get_usd_per_cere(), +// usd_per_cere, +// "conversion rate must be changed" +// ); +// } + +// #[ink::test] +// #[should_panic] +// fn currency_conversion_set_rate_only_admin() { +// let mut contract = setup(); +// let not_admin = get_accounts().bob; + +// set_caller(not_admin); +// contract.account_set_usd_per_cere(9); +// } From 9445a341620cc1fff6791cfb97dac1ffb7558ee3 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Tue, 27 Jun 2023 23:46:44 +0200 Subject: [PATCH 39/89] chore(test): replacing a node scenario is recovered --- bucket/ddc_bucket/tests/test_contract.rs | 153 +++++++++++------------ bucket/ddc_bucket/topology/store.rs | 4 +- 2 files changed, 74 insertions(+), 83 deletions(-) diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index 9d73e31a..08dde5ce 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -490,93 +490,82 @@ fn cluster_create_works() { } -// #[ink::test] -// fn cluster_replace_node_only_manager() { -// let mut ctx = new_cluster(); -// let not_manager = get_accounts().alice; -// set_caller_value(not_manager, 0); - -// // Reassign a vnode from node1 to node2. -// assert_eq!( -// ctx.contract -// .message_cluster_replace_node( -// ctx.cluster_id, -// vec![1, 2, 3], -// ctx.node_key2 -// ), -// Err(OnlyClusterManager) -// ); -// } - -// #[ink::test] -// fn cluster_replace_node_only_trusted_manager() { -// let mut ctx = new_cluster(); - -// // The provider stops trusting the manager_id. -// set_caller(ctx.provider_id2); -// ctx.contract.node_distrust_manager(ctx.manager_id); - -// set_caller_value(ctx.manager_id, 0); - -// // The manager_id cannot use nodes of the provider. -// assert_eq!( -// ctx.contract -// .message_cluster_replace_node( -// ctx.cluster_id, -// vec![1, 2, 3], -// ctx.node_key2 -// ), -// Err(OnlyTrustedClusterManager) -// ); -// } - -// #[ink::test] -// fn cluster_replace_node_works() { -// let mut ctx = new_cluster(); -// set_caller_value(ctx.manager_id, 0); -// // Reassign a vnode from node1 to node2. -// ctx.contract -// .cluster_replace_node(ctx.cluster_id, vec![1, 3], ctx.node_key2); - -// // Check the last event. -// let ev = get_events().pop().unwrap(); -// assert!(matches!(ev, Event::ClusterNodeReplaced(ev) if ev == -// ClusterNodeReplaced { cluster_id: ctx.cluster_id, node_key: ctx.node_key2 })); - -// let vnodes_for_replaced = vec![2]; -// let vnodes_for_second_node = vec![4, 5, 6]; -// let vnodes_for_third_node = vec![7, 8, 9]; -// let vnodes_for_third_dup = vec![1, 3]; +#[ink::test] +fn cluster_replace_node_only_manager() { + let mut ctx = new_cluster(); + let not_manager = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_caller_value(not_manager, 0); + + // Reassign a vnode from node1 to node2. + assert_eq!( + ctx.contract.cluster_replace_node( + ctx.cluster_id, + vec![1, 2, 3], + ctx.node_key2 + ), + Err(OnlyClusterManager) + ); +} -// let vnodes = vec![ -// vnodes_for_replaced, -// vnodes_for_second_node, -// vnodes_for_third_node, -// vnodes_for_third_dup, -// ]; +#[ink::test] +fn cluster_replace_node_works() { + let mut ctx = new_cluster(); + set_caller_value(ctx.manager_id, 0); + + // Reassign a vnode from node1 to node2. + ctx.contract.cluster_replace_node( + ctx.cluster_id, + vec![1, 3], + ctx.node_key2 + ).unwrap(); -// // Check the changed state of the cluster. -// let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; -// println!("cluster.v_nodes: {:?}", cluster.v_nodes.clone()); -// println!("cluster.node_keys: {:?}", cluster.node_keys.clone()); -// assert_eq!(&cluster.v_nodes, &vnodes, "a vnode must be replaced"); + // Check the last event. + let ev = get_events().pop().unwrap(); + assert!(matches!(ev, Event::ClusterNodeReplaced(ev) if ev == + ClusterNodeReplaced { + cluster_id: ctx.cluster_id, + node_key: ctx.node_key2 + } + )); -// // Check the changed state of the nodes. -// let expected_resources = [ -// (ctx.node_key0, 100 - 10), -// (ctx.node_key1, 100 - 10 - 10 - 10), -// (ctx.node_key2, 100 - 10 - 10 - 10 - 10 - 10), -// ]; + let mut cluster_v_nodes = Vec::::new(); + cluster_v_nodes.extend(vec![2]); + cluster_v_nodes.extend(ctx.v_nodes_by_nodes[1].clone()); + cluster_v_nodes.extend(ctx.v_nodes_by_nodes[2].clone()); + cluster_v_nodes.extend(vec![1, 3]); + cluster_v_nodes.sort(); + + let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; + cluster_info.cluster_v_nodes.sort(); + assert_eq!(&cluster_info.cluster_v_nodes, &cluster_v_nodes, "a v_node must be replaced"); + + let mut v_nodes0 = ctx.contract.get_v_nodes_by_node(ctx.node_key0.clone()); + v_nodes0.sort(); + let mut v_nodes1 = ctx.contract.get_v_nodes_by_node(ctx.node_key1.clone()); + v_nodes1.sort(); + let mut v_nodes2 = ctx.contract.get_v_nodes_by_node(ctx.node_key2.clone()); + v_nodes2.sort(); + + assert_eq!(&v_nodes0, &vec![2], "v_nodes must be replaced for the 1st node"); + assert_eq!(&v_nodes1, &vec![4, 5, 6], "v_nodes must not be replaced for the 2nd node"); + assert_eq!(&v_nodes2, &vec![1, 3, 7, 8, 9], "v_nodes must be assigned to the 3rd node"); + + // Check the changed state of the nodes. + let expected_resources = [ + (ctx.node_key0, 100 - 10), + (ctx.node_key1, 100 - 10 - 10 - 10), + (ctx.node_key2, 100 - 10 - 10 - 10 - 10 - 10), + ]; -// for (node_key, available) in expected_resources { -// let node_status = ctx.contract.node_get(node_key).unwrap(); -// assert_eq!( -// node_status.node.free_resource, available, -// "resources must have shifted between nodes" -// ); -// } -// } + for (node_key, available) in expected_resources { + let node_status = ctx.contract.node_get(node_key).unwrap(); + assert_eq!( + node_status.node.free_resource, available, + "resources must have shifted between nodes" + ); + } +} // #[ink::test] // fn cluster_reserve_works() { diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index 4c26723d..33ad75e5 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -152,7 +152,9 @@ impl TopologyStore { } // vnodes that are being reasigned should be among other vnodes assigned to the new physical node - self.v_nodes_map.insert(new_node_key, &v_nodes_to_reasign); + let mut new_node_v_nodes = self.get_v_nodes_by_node(new_node_key); + new_node_v_nodes.extend(v_nodes_to_reasign); + self.v_nodes_map.insert(new_node_key, &new_node_v_nodes); Ok(()) } From cef1c234ee1c7fa3e7fd9d8a11270c7dfa76224a Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 28 Jun 2023 01:30:56 +0200 Subject: [PATCH 40/89] chore(test): tests for adding nodes are recovered --- bucket/ddc_bucket/tests/test_contract.rs | 1249 ++++++++++------------ bucket/ddc_bucket/tests/test_currency.rs | 104 +- 2 files changed, 639 insertions(+), 714 deletions(-) diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index 08dde5ce..4415fe59 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -23,22 +23,24 @@ const KB_PER_GB: Balance = 1_048_576; struct TestCluster { contract: DdcBucket, - manager_id: AccountId, - cluster_id: ClusterId, - cluster_params: ClusterParams, provider_id0: AccountId, provider_id1: AccountId, provider_id2: AccountId, node_key0: NodeKey, node_key1: NodeKey, node_key2: NodeKey, - rent_per_v_node: Balance, - nodes_keys: Vec, node_params0: NodeParams, node_params1: NodeParams, node_params2: NodeParams, + v_nodes0: Vec, + v_nodes1: Vec, + v_nodes2: Vec, + manager_id: AccountId, + cluster_id: ClusterId, + cluster_params: ClusterParams, cluster_v_nodes: Vec, - v_nodes_by_nodes: Vec>, + nodes_keys: Vec, + rent_per_v_node: Balance, capacity: u32, reserved_resource: u32, } @@ -159,17 +161,10 @@ fn new_cluster() -> TestCluster { node_key2 ]; - let v_nodes_by_nodes = vec![ - v_nodes0.clone(), - v_nodes1.clone(), - v_nodes2.clone() - ]; - let mut cluster_v_nodes = Vec::::new(); - cluster_v_nodes.extend(v_nodes0); - cluster_v_nodes.extend(v_nodes1); - cluster_v_nodes.extend(v_nodes2); - + cluster_v_nodes.extend(v_nodes0.clone()); + cluster_v_nodes.extend(v_nodes1.clone()); + cluster_v_nodes.extend(v_nodes2.clone()); TestCluster { contract, @@ -182,9 +177,11 @@ fn new_cluster() -> TestCluster { node_key0, node_key1, node_key2, - rent_per_v_node, - v_nodes_by_nodes, + v_nodes0, + v_nodes1, + v_nodes2, cluster_v_nodes, + rent_per_v_node, nodes_keys, node_params0, node_params1, @@ -494,6 +491,7 @@ fn cluster_create_works() { #[ink::test] fn cluster_replace_node_only_manager() { let mut ctx = new_cluster(); + let not_manager = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); set_caller_value(not_manager, 0); @@ -511,16 +509,16 @@ fn cluster_replace_node_only_manager() { #[ink::test] fn cluster_replace_node_works() { let mut ctx = new_cluster(); - set_caller_value(ctx.manager_id, 0); - // Reassign a vnode from node1 to node2. + set_caller(ctx.manager_id); + // Reassign a vnode from node0 to node2. ctx.contract.cluster_replace_node( ctx.cluster_id, vec![1, 3], ctx.node_key2 - ).unwrap(); + )?; - // Check the last event. + // Check the last event let ev = get_events().pop().unwrap(); assert!(matches!(ev, Event::ClusterNodeReplaced(ev) if ev == ClusterNodeReplaced { @@ -531,8 +529,8 @@ fn cluster_replace_node_works() { let mut cluster_v_nodes = Vec::::new(); cluster_v_nodes.extend(vec![2]); - cluster_v_nodes.extend(ctx.v_nodes_by_nodes[1].clone()); - cluster_v_nodes.extend(ctx.v_nodes_by_nodes[2].clone()); + cluster_v_nodes.extend(ctx.v_nodes1.clone()); + cluster_v_nodes.extend(ctx.v_nodes2.clone()); cluster_v_nodes.extend(vec![1, 3]); cluster_v_nodes.sort(); @@ -559,351 +557,369 @@ fn cluster_replace_node_works() { ]; for (node_key, available) in expected_resources { - let node_status = ctx.contract.node_get(node_key).unwrap(); + let node_info = ctx.contract.node_get(node_key).unwrap(); assert_eq!( - node_status.node.free_resource, available, + node_info.node.free_resource, available, "resources must have shifted between nodes" ); } } -// #[ink::test] -// fn cluster_reserve_works() { -// let mut ctx = new_cluster(); -// set_caller_value(ctx.manager_id, 0); - -// // Reserve more resources. -// ctx.contract.cluster_reserve_resource(ctx.cluster_id, 5); - -// // Check the last event. -// let ev = get_events().pop().unwrap(); -// assert!(matches!(ev, Event::ClusterReserveResource(ev) if ev == -// ClusterReserveResource { cluster_id: ctx.cluster_id, resource: 5 })); - -// // Check the changed state of the cluster. -// let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; -// assert_eq!(cluster.resource_per_v_node, 10 + 5); - -// // Check the changed state of the nodes. -// let expected_resources = [ -// (ctx.node_key0, 100 - 40 - 5), -// (ctx.node_key1, 100 - 40 - 5), -// (ctx.node_key2, 100 - 40 - 5), -// ]; -// for (node_id, available) in expected_resources { -// assert_eq!( -// ctx.contract.node_get(node_id)?.node.free_resource, -// available, -// "more resources must be reserved from the nodes" -// ); -// } -// } -// #[ink::test] -// fn cluster_management_validation_works() { -// let mut ctx = new_cluster(); +#[ink::test] +fn cluster_reserve_works() { + let mut ctx = new_cluster(); + set_caller(ctx.manager_id); -// let not_manager = ctx.provider_id0; -// set_caller_value(not_manager, 0); + // Reserve more resources. + ctx.contract.cluster_reserve_resource(ctx.cluster_id, 5); -// assert_eq!( -// ctx.contract -// .message_cluster_replace_node( -// ctx.cluster_id, -// vec![1, 2, 3], -// AccountId::from([0x0a; 32]) -// ), -// Err(OnlyClusterManager), -// "only the manager_id can modify the cluster" -// ); + // Check the last event. + let ev = get_events().pop().unwrap(); + assert!(matches!(ev, Event::ClusterReserveResource(ev) if ev == + ClusterReserveResource { + cluster_id: ctx.cluster_id, + resource: 5 + } + )); -// set_caller_value(ctx.manager_id, 0); + // Check the changed state of the cluster. + let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; + assert_eq!(cluster.resource_per_v_node, 10 + 5); -// let bad_node_id = AccountId::from([0x0d; 32]); -// assert_eq!( -// ctx.contract -// .message_cluster_replace_node( -// ctx.cluster_id, -// vec![1, 2, 3], -// bad_node_id -// ), -// Err(NodeDoesNotExist), -// "cluster replacement node must exist" -// ); + // Check the changed state of the nodes. + let expected_resources = [ + (ctx.node_key0, 100 - 40 - 5), + (ctx.node_key1, 100 - 40 - 5), + (ctx.node_key2, 100 - 40 - 5), + ]; + for (node_id, available) in expected_resources { + assert_eq!( + ctx.contract.node_get(node_id)?.node.free_resource, + available, + "more resources must be reserved from the nodes" + ); + } +} -// assert_eq!( -// ctx.contract -// .message_cluster_create(vec![vec![1, 2, 3]], vec![bad_node_id], vec![1, 2, 3], "".to_string()), -// Err(NodeDoesNotExist), -// "cluster initial nodes must exist" -// ); -// } -// // #[ink::test] -// // fn cdn_cluster_gas_converter_works() { -// // println!("Creating new cdn cluster"); +#[ink::test] +fn cluster_management_validation_works() { + let mut ctx = new_cluster(); + + let not_manager = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_caller(not_manager); + assert_eq!( + ctx.contract.cluster_replace_node( + ctx.cluster_id, + vec![1, 2, 3], + ctx.node_key1.clone() + ), + Err(OnlyClusterManager), + "only the manager_id can modify the cluster" + ); + + let bad_node_id = AccountId::from([0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, 0x9c, 0x76]); + set_caller(ctx.manager_id); + assert_eq!( + ctx.contract + .cluster_replace_node( + ctx.cluster_id, + vec![1, 2, 3], + bad_node_id + ), + Err(NodeDoesNotExist), + "cluster replacement node must exist" + ); -// // let mut ctx = new_cluster_cdn(); +} -// // println!("Got cdn cluster back"); -// // // The provider stops trusting the manager_id. -// // println!("Cdn cluster id is {}", ctx.cluster_id); -// // set_caller(ctx.manager_id); -// // ctx.contract.cdn_set_rate(ctx.cluster_id, 3_750_000_000); -// // set_caller(ctx.provider_id0); -// // let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); +// #[ink::test] +// fn cdn_cluster_gas_converter_works() { +// println!("Creating new cdn cluster"); -// // let usd_per_cere = TOKEN / 100; -// // set_caller(ctx.provider_id0); -// // ctx.contract.account_set_usd_per_cere(usd_per_cere); +// let mut ctx = new_cluster_cdn(); -// // let usd_amount = ctx.contract.account_get_usd_per_cere(); -// // println!("Current usd amount is {}", usd_amount); +// println!("Got cdn cluster back"); +// // The provider stops trusting the manager_id. +// println!("Cdn cluster id is {}", ctx.cluster_id); +// set_caller(ctx.manager_id); +// ctx.contract.cdn_set_rate(ctx.cluster_id, 3_750_000_000); +// set_caller(ctx.provider_id0); +// let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); -// // println!("The current rate is {}", rate); +// let usd_per_cere = TOKEN / 100; +// set_caller(ctx.provider_id0); +// ctx.contract.account_set_usd_per_cere(usd_per_cere); -// // let usd_per_kb = rate / KB_PER_GB; -// // println!("The current rate per kb {}", usd_per_kb); +// let usd_amount = ctx.contract.account_get_usd_per_cere(); +// println!("Current usd amount is {}", usd_amount); -// // let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); -// // println!("The current cere rate per kb {}", cere_per_kb); -// // } - -// // #[ink::test] -// // fn cdn_cluster_payment_works() { -// // println!("Creating new cdn cluster"); - -// // let mut ctx = new_cluster_cdn(); - -// // println!("Got cdn cluster back"); -// // // The provider stops trusting the manager_id. -// // println!("Cdn cluster id is {}", ctx.cluster_id); -// // set_caller(ctx.provider_id0); -// // let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); - -// // let usd_per_cere = TOKEN / 100; -// // set_caller(ctx.provider_id0); -// // ctx.contract.account_set_usd_per_cere(usd_per_cere); - -// // let usd_amount = ctx.contract.account_get_usd_per_cere(); -// // println!("Current usd amount is {}", usd_amount); - -// // println!("The current rate is {}", rate); - -// // let usd_per_kb = rate / KB_PER_GB; -// // println!("The current rate per kb {}", usd_per_kb); - -// // let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); -// // println!("The current cere rate per kb {}", cere_per_kb); - -// // set_caller_value(ctx.provider_id0, 10 * TOKEN); -// // ctx.contract.account_deposit(); - -// // set_caller(ctx.provider_id0); -// // ctx.contract.account_bond(5 * TOKEN); - -// // set_caller(ctx.provider_id0); -// // ctx.contract.set_fee_bp(1_000); - -// // let mut account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); -// // println!("{:?}", account); - -// // ctx.contract.cdn_cluster_put_revenue( -// // ctx.cluster_id, -// // vec![(ctx.provider_id0, 1000), (ctx.provider_id0, 541643)], -// // vec![(ctx.node_key0, 1000), (ctx.node_key1, 541643)], -// // vec![], -// // 5, -// // ); -// // account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); -// // println!("{:?}", account); - -// // let cdn_cluster_list_one = ctx.contract.cdn_cluster_list(0, 10, None); -// // print!("Cluster list one {:?}", cdn_cluster_list_one); -// // let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); -// // let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); - -// // println!("Node 1 {:?}", node0); -// // println!("Node 2 {:?}", node1); -// // // let cdn_cluster0 = ctx.contract.cdn_clusters.get(ctx.cluster_id); -// // // print!("{:?}", cdn_cluster0); -// // // let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); -// // // print!("{:?}", cdn_cluster0); -// // // print!("{:?}", cdn_cluster_list); - -// // let validated_commit_node0 = ctx.contract.get_validated_commit(ctx.node_key0); -// // print!("Validated commit {:?}", validated_commit_node0); - -// // let fee = ctx.contract.get_fee_bp(); -// // print!("Protocol fee in basis points {:?}", fee); - -// // let protocol_revenues = ctx.contract.get_protocol_revenues(); -// // print!("Protocol revenues are {:?}", protocol_revenues); - -// // set_caller(ctx.provider_id0); -// // ctx.contract.cdn_cluster_distribute_revenues(0); - -// // let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); -// // let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); -// // println!("{:?}", node0); -// // println!("{:?}", node1); - -// // let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); -// // print!("{:?}", cdn_cluster_list); - -// // account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); -// // // let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); -// // // let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); -// // println!("{:?}", account); -// // // let account1 = ctx.contract.accounts.get(&ctx.provider_id1).unwrap(); -// // // println!("{:?}", account1); -// // // let account_balance = ink_env::balance(&ctx.provider_id0); -// // // println!("{:?}", account_balance); -// // } - -// fn bucket_settle_payment(ctx: &mut TestCluster, test_bucket: &TestBucket) { -// // Go to the future when some revenues are due. -// advance_block::(); -// // Pay the due thus far. -// set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); -// ctx.contract.bucket_settle_payment(test_bucket.bucket_id); -// } +// println!("The current rate is {}", rate); -// #[ink::test] -// fn bucket_pays_cluster() { -// let ctx = &mut new_cluster(); -// let test_bucket = &new_bucket(ctx); -// do_bucket_pays_cluster(ctx, test_bucket, 1).unwrap(); +// let usd_per_kb = rate / KB_PER_GB; +// println!("The current rate per kb {}", usd_per_kb); + +// let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); +// println!("The current cere rate per kb {}", cere_per_kb); // } // #[ink::test] -// fn bucket_pays_cluster_at_new_rate() { -// let ctx = &mut new_cluster(); -// let test_bucket = &new_bucket(ctx); +// fn cdn_cluster_payment_works() { +// println!("Creating new cdn cluster"); -// // Set up an exchange rate manager_id. -// set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); -// ctx.contract -// .admin_grant_permission(admin_id(), Permission::SetExchangeRate); +// let mut ctx = new_cluster_cdn(); -// // Change the currency exchange rate. -// let usd_per_cere = 2; -// set_caller(admin_id()); -// ctx.contract.account_set_usd_per_cere(usd_per_cere * TOKEN); +// println!("Got cdn cluster back"); +// // The provider stops trusting the manager_id. +// println!("Cdn cluster id is {}", ctx.cluster_id); +// set_caller(ctx.provider_id0); +// let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); -// do_bucket_pays_cluster(ctx, test_bucket, usd_per_cere).unwrap(); -// } +// let usd_per_cere = TOKEN / 100; +// set_caller(ctx.provider_id0); +// ctx.contract.account_set_usd_per_cere(usd_per_cere); -// fn do_bucket_pays_cluster( -// ctx: &mut TestCluster, -// test_bucket: &TestBucket, -// usd_per_cere: Balance, -// ) -> Result<()> { -// let expected_rent = ctx.rent_per_v_node * ctx.vnodes.len() as Balance; +// let usd_amount = ctx.contract.account_get_usd_per_cere(); +// println!("Current usd amount is {}", usd_amount); -// // Check the state before payment. -// let before = ctx -// .contract -// .account_get(test_bucket.owner_id)? -// .deposit -// .peek(); -// let bucket = ctx.contract.bucket_get(test_bucket.bucket_id)?.bucket; -// assert_eq!(bucket.owner_id, test_bucket.owner_id); -// /* TODO: Not testable at the moment, see struct BucketInStatus. -// assert_eq!(bucket.flow, -// Flow { -// from: test_bucket.owner_id, -// schedule: Schedule::new(0, expected_rent), -// }); -// */ -// let timestamp_before = block_timestamp::(); -// bucket_settle_payment(ctx, &test_bucket); -// let timestamp_after = block_timestamp::(); +// println!("The current rate is {}", rate); -// // Check the last event. -// let ev = get_events().pop().unwrap(); -// assert!(matches!(ev, Event::BucketSettlePayment(ev) if ev == -// BucketSettlePayment { bucket_id: test_bucket.bucket_id, cluster_id: ctx.cluster_id })); +// let usd_per_kb = rate / KB_PER_GB; +// println!("The current rate per kb {}", usd_per_kb); -// // Check the state after payment. -// let after = ctx -// .contract -// .account_get(test_bucket.owner_id)? -// .deposit -// .peek(); -// let spent = before - after; -// /* TODO: Not testable at the moment, see struct BucketInStatus. -// let bucket = ctx.contract.bucket_get(test_bucket.bucket_id)?.bucket; -// assert_eq!(bucket.flow, -// Flow { -// from: test_bucket.owner_id, -// schedule: Schedule::new(BLOCK_TIME, expected_rent), -// }); -// */ -// let timespan = timestamp_after - timestamp_before; -// let expect_revenues_usd = expected_rent * timespan as u128 / MS_PER_MONTH as u128; -// let expect_revenues = expect_revenues_usd / usd_per_cere; -// assert!(expect_revenues > 0); -// assert_eq!( -// expect_revenues, spent, -// "revenues must come from the bucket owner" -// ); +// let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); +// println!("The current cere rate per kb {}", cere_per_kb); -// let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; -// assert_eq!( -// cluster.revenues.peek(), -// expect_revenues, -// "must get revenues into the cluster" -// ); +// set_caller_value(ctx.provider_id0, 10 * TOKEN); +// ctx.contract.account_deposit(); + +// set_caller(ctx.provider_id0); +// ctx.contract.account_bond(5 * TOKEN); + +// set_caller(ctx.provider_id0); +// ctx.contract.set_fee_bp(1_000); -// Ok(()) +// let mut account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); +// println!("{:?}", account); + +// ctx.contract.cdn_cluster_put_revenue( +// ctx.cluster_id, +// vec![(ctx.provider_id0, 1000), (ctx.provider_id0, 541643)], +// vec![(ctx.node_key0, 1000), (ctx.node_key1, 541643)], +// vec![], +// 5, +// ); +// account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); +// println!("{:?}", account); + +// let cdn_cluster_list_one = ctx.contract.cdn_cluster_list(0, 10, None); +// print!("Cluster list one {:?}", cdn_cluster_list_one); +// let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); +// let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); + +// println!("Node 1 {:?}", node0); +// println!("Node 2 {:?}", node1); +// // let cdn_cluster0 = ctx.contract.cdn_clusters.get(ctx.cluster_id); +// // print!("{:?}", cdn_cluster0); +// // let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); +// // print!("{:?}", cdn_cluster0); +// // print!("{:?}", cdn_cluster_list); + +// let validated_commit_node0 = ctx.contract.get_validated_commit(ctx.node_key0); +// print!("Validated commit {:?}", validated_commit_node0); + +// let fee = ctx.contract.get_fee_bp(); +// print!("Protocol fee in basis points {:?}", fee); + +// let protocol_revenues = ctx.contract.get_protocol_revenues(); +// print!("Protocol revenues are {:?}", protocol_revenues); + +// set_caller(ctx.provider_id0); +// ctx.contract.cdn_cluster_distribute_revenues(0); + +// let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); +// let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); +// println!("{:?}", node0); +// println!("{:?}", node1); + +// let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); +// print!("{:?}", cdn_cluster_list); + +// account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); +// // let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); +// // let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); +// println!("{:?}", account); +// // let account1 = ctx.contract.accounts.get(&ctx.provider_id1).unwrap(); +// // println!("{:?}", account1); +// // let account_balance = ink_env::balance(&ctx.provider_id0); +// // println!("{:?}", account_balance); // } -// #[ink::test] -// fn cluster_add_node() { -// let ctx = &mut new_cluster(); +fn bucket_settle_payment(ctx: &mut TestCluster, test_bucket: &TestBucket) { + // Go to the future when some revenues are due. + advance_block::(); + // Pay the due thus far. + set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); + ctx.contract.bucket_settle_payment(test_bucket.bucket_id); +} -// let new_provider_id = get_accounts().frank; -// set_balance(new_provider_id, 1000 * TOKEN); +#[ink::test] +fn bucket_pays_cluster() { + let ctx = &mut new_cluster(); + let test_bucket = &new_bucket(ctx); + do_bucket_pays_cluster(ctx, test_bucket, 1).unwrap(); +} -// let rent_per_month = 100; -// let node_params = "new_node"; -// let capacity = 1000; -// let status = NodeStatusInCluster::ACTIVE; +#[ink::test] +fn bucket_pays_cluster_at_new_rate() { + let ctx = &mut new_cluster(); -// set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); -// let new_node_id = ctx.contract.node_create( -// AccountId::from([0x0d; 32]), -// rent_per_month, -// node_params.to_string(), -// capacity, -// status, -// ); + let test_bucket = &new_bucket(ctx); + // Set up an exchange rate manager_id. + set_caller(admin_id()); + ctx.contract + .admin_grant_permission(admin_id(), Permission::SetExchangeRate).unwrap(); -// set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); -// ctx.contract.node_trust_manager(ctx.manager_id); -// assert!( -// matches!(get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == -// PermissionGranted { account_id: ctx.manager_id, permission: Permission::ClusterManagerTrustedBy(new_provider_id) }) -// ); -// let mut node_keys = Vec::::new(); -// node_keys.push(ctx.node_key0); -// node_keys.push(ctx.node_key1); -// node_keys.push(ctx.node_key2); -// node_keys.push(new_node_id); + // Change the currency exchange rate. + let usd_per_cere = 2; + set_caller(admin_id()); + ctx.contract.account_set_usd_per_cere(usd_per_cere * TOKEN); + + do_bucket_pays_cluster(ctx, test_bucket, usd_per_cere).unwrap(); +} -// let mut v_nodes = ctx.vnodes_wrapper.clone(); -// v_nodes.push(vec![10, 11, 12]); +fn do_bucket_pays_cluster( + ctx: &mut TestCluster, + test_bucket: &TestBucket, + usd_per_cere: Balance, +) -> Result<()> { + let expected_rent = ctx.rent_per_v_node * ctx.cluster_v_nodes.len() as Balance; + + // Check the state before payment. + let before = ctx + .contract + .account_get(test_bucket.owner_id)? + .deposit + .peek(); + let bucket = ctx.contract.bucket_get(test_bucket.bucket_id)?.bucket; + assert_eq!(bucket.owner_id, test_bucket.owner_id); + /* TODO: Not testable at the moment, see struct BucketInStatus. + assert_eq!(bucket.flow, + Flow { + from: test_bucket.owner_id, + schedule: Schedule::new(0, expected_rent), + }); + */ + let timestamp_before = block_timestamp::(); + bucket_settle_payment(ctx, &test_bucket); + let timestamp_after = block_timestamp::(); + + // Check the last event. + let ev = get_events().pop().unwrap(); + assert!(matches!(ev, Event::BucketSettlePayment(ev) if ev == + BucketSettlePayment { + bucket_id: test_bucket.bucket_id, + cluster_id: ctx.cluster_id + } + )); + + // Check the state after payment. + let after = ctx + .contract + .account_get(test_bucket.owner_id)? + .deposit + .peek(); + let spent = before - after; + /* TODO: Not testable at the moment, see struct BucketInStatus. + let bucket = ctx.contract.bucket_get(test_bucket.bucket_id)?.bucket; + assert_eq!(bucket.flow, + Flow { + from: test_bucket.owner_id, + schedule: Schedule::new(BLOCK_TIME, expected_rent), + }); + */ + let timespan = timestamp_after - timestamp_before; + let expect_revenues_usd = expected_rent * timespan as u128 / MS_PER_MONTH as u128; + let expect_revenues = expect_revenues_usd / usd_per_cere; + assert!(expect_revenues > 0); + assert_eq!( + expect_revenues, spent, + "revenues must come from the bucket owner" + ); + + let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; + assert_eq!( + cluster.revenues.peek(), + expect_revenues, + "must get revenues into the cluster" + ); + + Ok(()) +} + +#[ink::test] +fn cluster_add_node_works() { + let mut ctx = new_cluster(); + + let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + set_balance(new_provider_id, 1000 * TOKEN); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let rent_per_month = 100; + let node_params = NodeParams::from("new_node"); + let capacity = 1000; + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + let new_node_key = ctx.contract.node_create( + new_node_key, + node_params.clone(), + capacity, + rent_per_month + )?; + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + ctx.contract.grant_trusted_manager_permission(ctx.manager_id)?; + assert!( + matches!( + get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == + PermissionGranted { + account_id: ctx.manager_id, + permission: Permission::ClusterManagerTrustedBy(new_provider_id) + } + ) + ); + + let new_v_nodes = vec![10, 11, 12]; + set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); + ctx.contract.cluster_add_node( + ctx.cluster_id, + new_node_key, + new_v_nodes.clone() + )?; + + let nodes_keys = vec![ + ctx.node_key0, + ctx.node_key1, + ctx.node_key2, + new_node_key, + ]; + + let cluster_v_nodes = vec![ + ctx.v_nodes0, + ctx.v_nodes1, + ctx.v_nodes2, + new_v_nodes + ]; + + let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; + cluster_info.cluster_v_nodes.sort(); + assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); + assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); +} -// set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); -// ctx.contract -// .cluster_add_node(ctx.cluster_id, node_keys.clone(), v_nodes.clone()); -// let cluster_status = ctx.contract.cluster_get(ctx.cluster_id).unwrap(); -// assert!(matches!(cluster_status.clone().cluster.node_keys.len(), 4)); -// assert!(matches!(cluster_status.clone().cluster.v_nodes.len(), 4)); -// } // #[ink::test] // fn cluster_pays_providers() { @@ -1002,271 +1018,222 @@ fn cluster_replace_node_works() { // ); // } -// #[ink::test] -// fn bucket_reserve_0_works() { -// let contract = setup(); -// assert_eq!( -// contract.bucket_list(0, 10, None), -// ( -// vec![BucketStatus { -// bucket_id: 0, -// bucket: BucketInStatus { -// owner_id: AccountId::default(), -// cluster_id: 0, -// resource_reserved: 0, -// public_availability: false, -// resource_consumption_cap: 0, -// }, -// params: "".to_string(), -// writer_ids: vec![AccountId::default()], -// reader_ids: vec![], -// rent_covered_until_ms: 18446744073709551615, -// }], -// 1 -// ) -// ); - -// assert_eq!( -// contract.cluster_list(0, 10, None), -// ( -// vec![ClusterInfo { -// cluster_id: 0, -// cluster: Cluster { -// manager_id: AccountId::default(), -// v_nodes: vec![], -// resource_per_v_node: 0, -// resource_used: 0, -// revenues: Cash(0), -// total_rent: 0, -// node_keys: vec![] -// }, -// params: "".to_string(), -// }], -// 1 -// ) -// ); - -// assert_eq!( -// contract.node_list(0, 10, None), -// ( -// vec![NodeInfo { -// node_key: AccountId::default(), -// node: Node { -// provider_id: AccountId::default(), -// rent_per_month: 0, -// free_resource: 0, -// status: NodeStatusInCluster::ACTIVE, -// node_params: "".to_string(), -// } -// }], -// 1 -// ) -// ); -// } +#[ink::test] +fn bucket_create_works() { + let ctx = &mut new_cluster(); + let test_bucket = &new_bucket(ctx); + + // Check the structure of the bucket including the payment flow. + let total_rent = ctx.rent_per_v_node * ctx.cluster_v_nodes.len() as Balance; + let expect_bucket = Bucket { + owner_id: test_bucket.owner_id, + cluster_id: ctx.cluster_id, + flow: Flow { + from: test_bucket.owner_id, + schedule: Schedule::new(0, total_rent), + }, + resource_reserved: test_bucket.resource, + public_availability: false, + resource_consumption_cap: 0, + }; + + // Check the status of the bucket. + let bucket_status = ctx.contract.bucket_get(test_bucket.bucket_id)?; + assert_eq!( + bucket_status, + BucketStatus { + bucket_id: test_bucket.bucket_id, + bucket: expect_bucket.into(), + params: "{}".to_string(), + writer_ids: vec![test_bucket.owner_id], + reader_ids: vec![], + rent_covered_until_ms: 297600000, // TODO: check this value. + } + ); -// #[ink::test] -// fn bucket_create_works() { -// let ctx = &mut new_cluster(); -// let test_bucket = &new_bucket(ctx); + let mut events = get_events(); + events.reverse(); // Work with pop(). + events.truncate(8 - 3 - 2); // Skip 3 NodeCreated and 2 cluster setup events. -// assert_eq!(test_bucket.bucket_id, 1, "bucket_id must start at 1"); - -// // Check the structure of the bucket including the payment flow. -// let total_rent = ctx.rent_per_v_node * ctx.vnodes.len() as Balance; -// let expect_bucket = Bucket { -// owner_id: test_bucket.owner_id, -// cluster_id: ctx.cluster_id, -// flow: Flow { -// from: test_bucket.owner_id, -// schedule: Schedule::new(0, total_rent), -// }, -// resource_reserved: test_bucket.resource, -// public_availability: false, -// resource_consumption_cap: 0, -// }; - -// // Check the status of the bucket. -// let bucket_status = ctx.contract.bucket_get(test_bucket.bucket_id)?; -// assert_eq!( -// bucket_status, -// BucketStatus { -// bucket_id: test_bucket.bucket_id, -// bucket: expect_bucket.into(), -// params: "{}".to_string(), -// writer_ids: vec![test_bucket.owner_id], -// reader_ids: vec![], -// rent_covered_until_ms: 297600000, // TODO: check this value. -// } -// ); + // Create bucket. + assert!( + matches!(events.pop().unwrap(), Event::BucketCreated(ev) if ev == + BucketCreated { bucket_id: test_bucket.bucket_id, owner_id: test_bucket.owner_id }) + ); -// let mut events = get_events(); -// events.reverse(); // Work with pop(). -// events.truncate(8 - 3 - 2); // Skip 3 NodeCreated and 2 cluster setup events. + assert!( + matches!(events.pop().unwrap(), Event::BucketAllocated(ev) if ev == + BucketAllocated { bucket_id: test_bucket.bucket_id, cluster_id: ctx.cluster_id, resource: test_bucket.resource }) + ); -// // Create bucket. -// assert!( -// matches!(events.pop().unwrap(), Event::BucketCreated(ev) if ev == -// BucketCreated { bucket_id: test_bucket.bucket_id, owner_id: test_bucket.owner_id }) -// ); + // Deposit more. + let net_deposit = 10 * TOKEN; + assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == + Deposit { account_id: test_bucket.owner_id, value: net_deposit })); -// assert!( -// matches!(events.pop().unwrap(), Event::BucketAllocated(ev) if ev == -// BucketAllocated { bucket_id: test_bucket.bucket_id, cluster_id: ctx.cluster_id, resource: test_bucket.resource }) -// ); + assert_eq!(events.len(), 0, "all events must be checked"); +} -// // Deposit more. -// let net_deposit = 10 * TOKEN; -// assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == -// Deposit { account_id: test_bucket.owner_id, value: net_deposit })); -// assert_eq!(events.len(), 0, "all events must be checked"); -// } -// #[ink::test] -// fn account_deposit_works() { -// let account_id = get_accounts().alice; -// let mut contract = setup(); +#[ink::test] +fn account_deposit_works() { + let account_id = get_accounts().alice; + let mut contract = setup(); -// assert_eq!( -// contract.account_get(account_id), -// Err(AccountDoesNotExist), -// "must not get a non-existent account" -// ); + assert_eq!( + contract.account_get(account_id), + Err(AccountDoesNotExist), + "must not get a non-existent account" + ); -// let deposit = 10 * TOKEN; -// let deposit_after_fee = deposit; + let deposit = 10 * TOKEN; + let deposit_after_fee = deposit; -// // Deposit some value. -// set_caller_value(account_id, deposit); -// contract.account_deposit(); + // Deposit some value. + set_caller_value(account_id, deposit); + contract.account_deposit(); -// let account = contract.account_get(account_id)?; -// assert_eq!( -// account, -// Account { -// deposit: Cash(deposit_after_fee), -// payable_schedule: Schedule::empty(), -// bonded: Cash(0), -// unbonded_amount: Cash(0), -// negative: Cash(0), -// unbonded_timestamp: 0, -// }, -// "must take deposit minus creation fee" -// ); + let account = contract.account_get(account_id)?; + assert_eq!( + account, + Account { + deposit: Cash(deposit_after_fee), + payable_schedule: Schedule::empty(), + bonded: Cash(0), + unbonded_amount: Cash(0), + negative: Cash(0), + unbonded_timestamp: 0, + }, + "must take deposit minus creation fee" + ); -// // Deposit more value. -// set_caller_value(account_id, deposit); -// contract.account_deposit(); + // Deposit more value. + set_caller_value(account_id, deposit); + contract.account_deposit(); -// let account = contract.account_get(account_id)?; -// assert_eq!( -// account, -// Account { -// deposit: Cash(deposit_after_fee + deposit), -// payable_schedule: Schedule::empty(), -// bonded: Cash(0), -// unbonded_amount: Cash(0), -// negative: Cash(0), -// unbonded_timestamp: 0, -// }, -// "must take more deposits without creation fee" -// ); + let account = contract.account_get(account_id)?; + assert_eq!( + account, + Account { + deposit: Cash(deposit_after_fee + deposit), + payable_schedule: Schedule::empty(), + bonded: Cash(0), + unbonded_amount: Cash(0), + negative: Cash(0), + unbonded_timestamp: 0, + }, + "must take more deposits without creation fee" + ); -// // Check events. -// let mut events = get_events(); -// events.reverse(); // Work with pop(). + // Check events. + let mut events = get_events(); + events.reverse(); // Work with pop(). -// // First deposit event. -// assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == -// Deposit { account_id, value: deposit_after_fee })); + // First deposit event. + assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == + Deposit { account_id, value: deposit_after_fee })); -// // Second deposit event. No deposit_contract_fee because the account already exists. -// assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == -// Deposit { account_id, value: deposit })); + // Second deposit event. No deposit_contract_fee because the account already exists. + assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == + Deposit { account_id, value: deposit })); -// assert_eq!(events.len(), 0, "all events must be checked"); -// } + assert_eq!(events.len(), 0, "all events must be checked"); +} -// #[ink::test] -// fn node_change_params_works() { -// let ctx = &mut new_cluster(); -// // Change params. -// set_caller_value(ctx.provider_id0, CONTRACT_FEE_LIMIT); -// ctx.contract -// .node_change_params(ctx.node_key0, "new params".to_string()); +#[ink::test] +fn node_set_params_works() { + let mut ctx = new_cluster(); -// // Check the changed params. -// let status = ctx.contract.node_get(ctx.node_key0)?; -// assert_eq!(status.node.node_params, "new params"); -// } + // Change params. + let new_node_params = NodeParams::from("new node params"); + set_caller_value(ctx.provider_id0, CONTRACT_FEE_LIMIT); + ctx.contract.node_set_params(ctx.node_key0, new_node_params.clone())?; -// #[ink::test] -// #[should_panic] -// fn node_change_params_only_owner() { -// let ctx = &mut new_cluster(); + // Check the changed params. + let status = ctx.contract.node_get(ctx.node_key0)?; + assert_eq!(status.node.node_params, new_node_params); +} -// // Change params. -// set_caller_value(get_accounts().bob, CONTRACT_FEE_LIMIT); -// ctx.contract -// .node_change_params(ctx.node_key0, "new params".to_string()); -// // Panic. -// } +#[ink::test] +fn node_set_params_only_owner() { + let mut ctx = new_cluster(); -// #[ink::test] -// fn cluster_change_params_works() { -// let ctx = &mut new_cluster(); + let not_provider = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + // Change params.not_provider + let new_node_params = NodeParams::from("new node params"); + set_caller_value(not_provider, CONTRACT_FEE_LIMIT); -// // Change params. -// set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); -// ctx.contract -// .cluster_change_params(ctx.cluster_id, "new params".to_string()); + assert_eq!( + ctx.contract.node_set_params( + ctx.node_key0, + new_node_params + ), + Err(OnlyNodeOwner) + ); +} -// // Check the changed params. -// let status = ctx.contract.cluster_get(ctx.cluster_id)?; -// assert_eq!(status.params, "new params"); -// } +#[ink::test] +fn cluster_change_params_works() { + let mut ctx = new_cluster(); -// #[ink::test] -// #[should_panic] -// fn cluster_change_params_only_owner() { -// let ctx = &mut new_cluster(); + // Change params. + let new_cluster_params = NodeParams::from("new cluster params"); + set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); + ctx.contract.cluster_set_params(ctx.cluster_id, new_cluster_params.clone())?; -// // Change params. -// set_caller_value(get_accounts().bob, CONTRACT_FEE_LIMIT); -// ctx.contract -// .cluster_change_params(ctx.cluster_id, "new params".to_string()); -// // Panic. -// } + // Check the changed params. + let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; + assert_eq!(cluster_info.cluster.cluster_params, new_cluster_params); +} -// #[ink::test] -// fn bucket_change_params_works() { -// let ctx = &mut new_cluster(); -// let test_bucket = &new_bucket(ctx); +#[ink::test] +fn cluster_change_params_only_owner() { + let ctx = &mut new_cluster(); -// // Change params. -// set_caller_value(test_bucket.owner_id, CONTRACT_FEE_LIMIT); -// ctx.contract -// .bucket_change_params(test_bucket.bucket_id, "new params".to_string()); + let not_manager = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + // Change params. + let new_cluster_params = NodeParams::from("new cluster params"); + set_caller_value(not_manager, CONTRACT_FEE_LIMIT); -// // Check the changed params. -// let status = ctx.contract.bucket_get(test_bucket.bucket_id)?; -// assert_eq!(status.params, "new params"); -// } + assert_eq!( + ctx.contract.cluster_set_params( + ctx.cluster_id, + new_cluster_params + ), + Err(OnlyClusterManager) + ); +} -// #[ink::test] -// #[should_panic] -// fn bucket_change_params_only_owner() { -// let ctx = &mut new_cluster(); -// let test_bucket = &new_bucket(ctx); +#[ink::test] +fn bucket_change_params_works() { + let ctx = &mut new_cluster(); + let test_bucket = &new_bucket(ctx); + + // Change params. + set_caller_value(test_bucket.owner_id, CONTRACT_FEE_LIMIT); + ctx.contract + .bucket_change_params(test_bucket.bucket_id, "new params".to_string()); + + // Check the changed params. + let status = ctx.contract.bucket_get(test_bucket.bucket_id)?; + assert_eq!(status.params, "new params"); +} -// // Change params. -// set_caller_value(get_accounts().bob, CONTRACT_FEE_LIMIT); -// ctx.contract -// .bucket_change_params(test_bucket.bucket_id, "new params".to_string()); -// // Panic. -// } +#[ink::test] +#[should_panic] +fn bucket_change_params_only_owner() { + let ctx = &mut new_cluster(); + let test_bucket = &new_bucket(ctx); + + // Change params. + set_caller_value(get_accounts().bob, CONTRACT_FEE_LIMIT); + ctx.contract + .bucket_change_params(test_bucket.bucket_id, "new params".to_string()); + // Panic. +} // #[ink::test] // fn bucket_list_works() { @@ -1338,121 +1305,79 @@ fn cluster_replace_node_works() { // ); // } -// #[ink::test] -// fn bucket_set_availability_works() { -// let ctx = &mut new_cluster(); -// let test_bucket = &new_bucket(ctx); -// let status = ctx.contract.bucket_get(test_bucket.bucket_id)?; -// assert_eq!(status.bucket.public_availability, false); - -// // Set public availability -// ctx.contract -// .bucket_set_availability(test_bucket.bucket_id, true); - -// // Check the last event. -// let ev = get_events().pop().unwrap(); -// assert!(matches!(ev, Event::BucketAvailabilityUpdated(ev) if ev == -// BucketAvailabilityUpdated { bucket_id: test_bucket.bucket_id, public_availability: true })); - -// // Check the changed params. -// let status = ctx.contract.bucket_get(test_bucket.bucket_id)?; -// assert_eq!(status.bucket.public_availability, true); -// } - -// #[ink::test] -// fn node_list_works() { -// let mut ddc_bucket = setup(); -// let accounts = get_accounts(); -// let owner_id1 = accounts.alice; -// let owner_id2 = accounts.bob; -// let owner_id3 = accounts.charlie; -// let rent_per_month: Balance = 10 * TOKEN; -// // Create two Nodes. -// let node_params1 = "{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"; -// let capacity = 100; -// set_caller_value(owner_id1, CONTRACT_FEE_LIMIT); -// let node_key1 = ddc_bucket.node_create( -// AccountId::from([0x0b; 32]), -// rent_per_month, -// node_params1.to_string(), -// capacity, -// NodeStatusInCluster::ADDING, -// ); -// let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; -// set_caller_value(owner_id2, CONTRACT_FEE_LIMIT); -// let node_key2 = ddc_bucket.node_create( -// AccountId::from([0x0c; 32]), -// rent_per_month, -// node_params2.to_string(), -// capacity, -// NodeStatusInCluster::ADDING, -// ); +#[ink::test] +fn node_list_works() { + let mut ctx = new_cluster(); -// let node_status = ddc_bucket.node_get(AccountId::from([0x0b; 32])).unwrap(); -// assert_eq!(owner_id1, node_status.node.provider_id.clone()); + let node_info = ctx.contract.node_get(ctx.node_key1)?; + assert_eq!(ctx.provider_id1, node_info.node.provider_id.clone()); + + let node1 = NodeInfo { + node_key: ctx.node_key1, + node: Node { + provider_id: ctx.provider_id1, + rent_per_month: ctx.rent_per_v_node, + free_resource: ctx.capacity - ctx.reserved_resource * 3, + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + node_params: ctx.node_params1, + }, + v_nodes: ctx.v_nodes1.clone() + }; + + let node2 = NodeInfo { + node_key: ctx.node_key2, + node: Node { + provider_id:ctx.provider_id2, + rent_per_month: ctx.rent_per_v_node, + free_resource: ctx.capacity - ctx.reserved_resource * 3, + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + node_params: ctx.node_params2, + }, + v_nodes: ctx.v_nodes2.clone() + }; -// assert_ne!(node_key1, node_key2); -// let count = 3; + assert_eq!( + ctx.contract.node_list(1, 100, None), + (vec![node1.clone(), node2.clone()], 3) + ); -// let node1 = NodeInfo { -// node_key: node_key1, -// node: Node { -// provider_id: owner_id1, -// rent_per_month, -// free_resource: capacity, -// status: NodeStatusInCluster::ADDING, -// node_params: node_params1.to_string(), -// }, -// }; - -// let node2 = NodeInfo { -// node_key: node_key2, -// node: Node { -// provider_id: owner_id2, -// rent_per_month, -// free_resource: capacity, -// status: NodeStatusInCluster::ADDING, -// node_params: node_params2.to_string(), -// }, -// }; + assert_eq!( + ctx.contract.node_list(1, 2, None), + (vec![node1.clone(), node2.clone()], 3) + ); -// assert_eq!( -// ddc_bucket.node_list(1, 100, None), -// (vec![node1.clone(), node2.clone()], count) -// ); + assert_eq!( + ctx.contract.node_list(1, 1, None), + (vec![node1.clone() /*, node2.clone()*/], 3) + ); -// assert_eq!( -// ddc_bucket.node_list(1, 2, None), -// (vec![node1.clone(), node2.clone()], count) -// ); + assert_eq!( + ctx.contract.node_list(2, 1, None), + (vec![/*node1.clone(),*/ node2.clone()], 3) + ); -// assert_eq!( -// ddc_bucket.node_list(1, 1, None), -// (vec![node1.clone() /*, node2.clone()*/], count) -// ); + assert_eq!(ctx.contract.node_list(21, 20, None), (vec![], 3)); -// assert_eq!( -// ddc_bucket.node_list(2, 1, None), -// (vec![/*node1.clone(),*/ node2.clone()], count) -// ); + // Filter by owner. + assert_eq!( + ctx.contract.node_list(1, 100, Some(ctx.provider_id1)), + (vec![node1.clone() /*, node2.clone()*/], 3) + ); -// assert_eq!(ddc_bucket.node_list(21, 20, None), (vec![], count)); + assert_eq!( + ctx.contract.node_list(1, 100, Some(ctx.provider_id2)), + (vec![/*node1.clone(),*/ node2.clone()], 3) + ); -// // Filter by owner. -// assert_eq!( -// ddc_bucket.node_list(1, 100, Some(owner_id1)), -// (vec![node1.clone() /*, node2.clone()*/], count) -// ); + let not_provider= AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); -// assert_eq!( -// ddc_bucket.node_list(1, 100, Some(owner_id2)), -// (vec![/*node1.clone(),*/ node2.clone()], count) -// ); -// assert_eq!( -// ddc_bucket.node_list(1, 100, Some(owner_id3)), -// (vec![], count) -// ); -// } + assert_eq!( + ctx.contract.node_list(1, 100, Some(not_provider)), + (vec![], 3) + ); +} diff --git a/bucket/ddc_bucket/tests/test_currency.rs b/bucket/ddc_bucket/tests/test_currency.rs index a7319927..e64c5fef 100644 --- a/bucket/ddc_bucket/tests/test_currency.rs +++ b/bucket/ddc_bucket/tests/test_currency.rs @@ -1,52 +1,52 @@ -// use ink_lang as ink; - -// use crate::ddc_bucket::*; - -// use super::env_utils::*; - -// fn setup() -> DdcBucket { -// set_caller(admin_id()); -// set_callee(contract_id()); -// let mut contract = DdcBucket::new(); -// set_balance(contract_id(), CONTRACT_FEE_LIMIT); -// contract.admin_grant_permission(admin_id(), Permission::SetExchangeRate); -// contract -// } - -// #[ink::test] -// fn currency_conversion_init_works() { -// let contract = setup(); -// let usd_amount = contract.account_get_usd_per_cere(); -// println!("{}", usd_amount); -// assert_eq!( -// contract.account_get_usd_per_cere(), -// 1 * TOKEN, -// "conversion rate must be 1 initially" -// ); -// } - -// #[ink::test] -// fn currency_conversion_set_rate_works() { -// let mut contract = setup(); -// let usd_per_cere = TOKEN / 10; -// println!("{}", usd_per_cere); - -// set_caller(admin_id()); -// contract.account_set_usd_per_cere(usd_per_cere); - -// assert_eq!( -// contract.account_get_usd_per_cere(), -// usd_per_cere, -// "conversion rate must be changed" -// ); -// } - -// #[ink::test] -// #[should_panic] -// fn currency_conversion_set_rate_only_admin() { -// let mut contract = setup(); -// let not_admin = get_accounts().bob; - -// set_caller(not_admin); -// contract.account_set_usd_per_cere(9); -// } +use ink_lang as ink; + +use crate::ddc_bucket::*; + +use super::env_utils::*; + +fn setup() -> DdcBucket { + set_caller(admin_id()); + set_callee(contract_id()); + let mut contract = DdcBucket::new(); + set_balance(contract_id(), CONTRACT_FEE_LIMIT); + contract.admin_grant_permission(admin_id(), Permission::SetExchangeRate); + contract +} + +#[ink::test] +fn currency_conversion_init_works() { + let contract = setup(); + let usd_amount = contract.account_get_usd_per_cere(); + println!("{}", usd_amount); + assert_eq!( + contract.account_get_usd_per_cere(), + 1 * TOKEN, + "conversion rate must be 1 initially" + ); +} + +#[ink::test] +fn currency_conversion_set_rate_works() { + let mut contract = setup(); + let usd_per_cere = TOKEN / 10; + println!("{}", usd_per_cere); + + set_caller(admin_id()); + contract.account_set_usd_per_cere(usd_per_cere); + + assert_eq!( + contract.account_get_usd_per_cere(), + usd_per_cere, + "conversion rate must be changed" + ); +} + +#[ink::test] +#[should_panic] +fn currency_conversion_set_rate_only_admin() { + let mut contract = setup(); + let not_admin = get_accounts().bob; + + set_caller(not_admin); + contract.account_set_usd_per_cere(9); +} From 61ada3d21366629d6796c0dd3683378260a1bb74 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 28 Jun 2023 16:07:41 +0200 Subject: [PATCH 41/89] chore(test): tests for revenue distribution are recovered --- bucket/ddc_bucket/bucket/messages.rs | 4 +- bucket/ddc_bucket/cluster/entity.rs | 2 - bucket/ddc_bucket/cluster/messages.rs | 13 +- bucket/ddc_bucket/tests/env_utils.rs | 2 +- bucket/ddc_bucket/tests/test_contract.rs | 816 ++++++++++++----------- bucket/ddc_bucket/tests/test_currency.rs | 2 +- 6 files changed, 419 insertions(+), 420 deletions(-) diff --git a/bucket/ddc_bucket/bucket/messages.rs b/bucket/ddc_bucket/bucket/messages.rs index 55a47a77..e7cd9155 100644 --- a/bucket/ddc_bucket/bucket/messages.rs +++ b/bucket/ddc_bucket/bucket/messages.rs @@ -183,8 +183,6 @@ impl DdcBucket { fn only_owner_or_cluster_manager(bucket: &Bucket, cluster: &Cluster) -> Result<()> { let caller = Self::env().caller(); - cluster.only_manager(caller) - .or_else(|_| - bucket.only_owner(caller)) + cluster.only_manager(caller).or_else(|_| bucket.only_owner(caller)) } } \ No newline at end of file diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 006db9a6..399eb0ba 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -29,7 +29,6 @@ pub struct Cluster { // cdn nodes pub cdn_nodes_keys: Vec, - pub cdn_resources_used: Resource, pub cdn_revenues: Cash, pub cdn_usd_per_gb: Balance, } @@ -69,7 +68,6 @@ impl Cluster { total_rent: 0, cdn_nodes_keys: Vec::new(), cdn_usd_per_gb: 104_857_600, // setting initially to 1 cent per GB - cdn_resources_used: 0, cdn_revenues: Cash(0), }; diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index b03631c0..6e92f324 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -12,7 +12,7 @@ use crate::ddc_bucket::perm::entity::Permission; use crate::ddc_bucket::ClusterNodeReplaced; use crate::ddc_bucket::{ AccountId, Balance, ClusterCreated, ClusterNodeAdded, ClusterNodeRemoved, - ClusterCdnNodeAdded, ClusterCdnNodeRemoved, ClusterDistributeRevenues, ClusterReserveResource, + ClusterCdnNodeAdded, ClusterCdnNodeRemoved, ClusterDistributeRevenues, CdnClusterDistributeRevenues, ClusterReserveResource, ClusterRemoved, ClusterParamsSet, ClusterNodeStatusSet, ClusterCdnNodeStatusSet, PermissionGranted, PermissionRevoked, DdcBucket, NodeStatusInCluster, Result, Error::* }; @@ -432,8 +432,7 @@ impl DdcBucket { )?; // Charge the provider payments from the cluster. - let cluster_v_nodes = self.topology_store.get_v_nodes_by_cluster(cluster_id); - let num_shares = cluster_v_nodes.len() as Balance; + let num_shares = cluster.nodes_keys.len() as Balance; let per_share = cluster.revenues.peek() / num_shares; cluster.revenues.pay(Payable(per_share * num_shares))?; @@ -561,13 +560,13 @@ impl DdcBucket { let mut cluster = self.clusters.get(cluster_id)?; // Charge the network fee from the cluster. - Self::capture_network_fee(&self.network_fee, &mut cluster.revenues)?; + Self::capture_network_fee(&self.network_fee, &mut cluster.cdn_revenues)?; // Charge the cluster management fee. Self::capture_fee( self.network_fee.cluster_management_fee_bp(), cluster.manager_id, - &mut cluster.revenues)?; + &mut cluster.cdn_revenues)?; // First accumulated revenues to distribute. let mut distributed_revenue = 0; @@ -578,7 +577,7 @@ impl DdcBucket { } // Charge the provider payments from the cluster. - cluster.revenues.pay(Payable(distributed_revenue))?; + cluster.cdn_revenues.pay(Payable(distributed_revenue))?; // Distribute revenues to nodes for cdn_node_key in &cluster.cdn_nodes_keys { @@ -588,7 +587,7 @@ impl DdcBucket { cdn_node.take_payment(cdn_node.undistributed_payment)?; self.cdn_nodes.update(*cdn_node_key, &cdn_node)?; - Self::env().emit_event(ClusterDistributeRevenues { + Self::env().emit_event(CdnClusterDistributeRevenues { cluster_id, provider_id: cdn_node.provider_id }); diff --git a/bucket/ddc_bucket/tests/env_utils.rs b/bucket/ddc_bucket/tests/env_utils.rs index aba4b2f1..64f6d2db 100644 --- a/bucket/ddc_bucket/tests/env_utils.rs +++ b/bucket/ddc_bucket/tests/env_utils.rs @@ -82,7 +82,7 @@ pub fn print_events(events: &[Event]) { Event::CdnClusterDistributeRevenues(ev) => println!("EVENT {:?}", ev), Event::CdnNodeCreated(ev) => println!("EVENT {:?}", ev), Event::ClusterNodeAdded(ev) => println!("EVENT {:?}", ev), - Event::ClusterCdnNodeAdded(ev) => println!("EVENT {:?}", ev), + Event::ClusterCdnNodeAdded(ev) => println!("{:?}", ev), Event::ClusterNodeRemoved(ev) => println!("EVENT {:?}", ev), Event::ClusterCdnNodeRemoved(ev) => println!("EVENT {:?}", ev), Event::ClusterParamsSet(ev) => println!("EVENT {:?}", ev), diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index 4415fe59..5a33b830 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -1,7 +1,6 @@ use ink_lang as ink; use crate::ddc_bucket::account::entity::Account; -// use crate::ddc_bucket::cdn_node::entity::CdnNodeKey; use crate::ddc_bucket::cluster::entity::ClusterInfo; use crate::ddc_bucket::flow::Flow; use crate::ddc_bucket::node::entity::{NodeStatusInCluster, NodeKey}; @@ -23,9 +22,11 @@ const KB_PER_GB: Balance = 1_048_576; struct TestCluster { contract: DdcBucket, + provider_id0: AccountId, provider_id1: AccountId, provider_id2: AccountId, + node_key0: NodeKey, node_key1: NodeKey, node_key2: NodeKey, @@ -35,11 +36,20 @@ struct TestCluster { v_nodes0: Vec, v_nodes1: Vec, v_nodes2: Vec, + + cdn_node_key0: CdnNodeKey, + cdn_node_key1: CdnNodeKey, + cdn_node_key2: CdnNodeKey, + cdn_node_params0: CdnNodeParams, + cdn_node_params1: CdnNodeParams, + cdn_node_params2: CdnNodeParams, + manager_id: AccountId, cluster_id: ClusterId, cluster_params: ClusterParams, cluster_v_nodes: Vec, nodes_keys: Vec, + cdn_nodes_keys: Vec, rent_per_v_node: Balance, capacity: u32, reserved_resource: u32, @@ -66,42 +76,73 @@ fn new_cluster() -> TestCluster { // Create the 1st storage node let node_key0 = AccountId::from([0x0a; 32]); - let node_params0 = NodeParams::from("{\"url\":\"https://ddc.cere.network/bucket/{BUCKET_ID}\"}"); - let capacity0 = 100; + let node_params0 = NodeParams::from("{\"url\":\"https://ddc.cere.network/storage/0\"}"); + let capacity0 = capacity; set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); contract.node_create( node_key0, node_params0.clone(), - capacity, + capacity0, rent_per_v_node ).unwrap(); // Create the 2nd storage node let node_key1 = AccountId::from([0x0b; 32]); - let node_params1 = NodeParams::from("{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"); - let capacity1 = 100; + let node_params1 = NodeParams::from("{\"url\":\"https://ddc-1.cere.network/storage/1\"}"); + let capacity1 = capacity; set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); contract.node_create( node_key1, node_params1.clone(), - capacity, + capacity1, rent_per_v_node ).unwrap(); // Create the 3rd storage node let node_key2 = AccountId::from([0x0c; 32]); - let node_params2 = NodeParams::from("{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"); + let node_params2 = NodeParams::from("{\"url\":\"https://ddc-2.cere.network/storage/2\"}"); + let capacity2 = capacity; set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); let node_key2 = contract.node_create( node_key2, node_params2.clone(), - capacity, + capacity2, rent_per_v_node, ).unwrap(); + // Create the 1st cdn node + let cdn_node_key0 = AccountId::from([0x0d; 32]); + let cdn_node_params0 = CdnNodeParams::from("{\"url\":\"https://ddc.cere.network/cdn/0\"}"); + set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); + contract.cdn_node_create( + cdn_node_key0, + cdn_node_params0.clone() + ).unwrap(); + + + // Create the 2nd cdn node + let cdn_node_key1 = AccountId::from([0x0e; 32]); + let cdn_node_params1 = CdnNodeParams::from("{\"url\":\"https://ddc.cere.network/cdn/1\"}"); + set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); + contract.cdn_node_create( + cdn_node_key1, + cdn_node_params1.clone() + ).unwrap(); + + + // Create the 3rd cdn node + let cdn_node_key2 = AccountId::from([0x0f; 32]); + let cdn_node_params2 = CdnNodeParams::from("{\"url\":\"https://ddc.cere.network/cdn/2\"}"); + set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); + contract.cdn_node_create( + cdn_node_key2, + cdn_node_params2.clone() + ).unwrap(); + + // Create a Cluster let cluster_params = ClusterParams::from("{}"); set_caller_value(manager_id, CONTRACT_FEE_LIMIT); @@ -118,10 +159,8 @@ fn new_cluster() -> TestCluster { assert!(contract.has_permission(manager_id, expected_perm)); } - println!("\n"); - - // Add the 1st node to the Cluster + // Add the 1st storage node to the Cluster let v_nodes0 = vec![1, 2, 3]; set_caller_value(manager_id, CONTRACT_FEE_LIMIT); contract.cluster_add_node( @@ -131,7 +170,7 @@ fn new_cluster() -> TestCluster { ).unwrap(); - // Add the 2nd node to the Cluster + // Add the 2nd storage node to the Cluster let v_nodes1 = vec![4, 5, 6]; set_caller_value(manager_id, CONTRACT_FEE_LIMIT); contract.cluster_add_node( @@ -141,7 +180,7 @@ fn new_cluster() -> TestCluster { ).unwrap(); - // Add the 3rd node to the Cluster + // Add the 3rd storage node to the Cluster let v_nodes2 = vec![7, 8, 9]; set_caller_value(manager_id, CONTRACT_FEE_LIMIT); contract.cluster_add_node( @@ -151,6 +190,30 @@ fn new_cluster() -> TestCluster { ).unwrap(); + // Add the 1st cdn node to the Cluster + set_caller_value(manager_id, CONTRACT_FEE_LIMIT); + contract.cluster_add_cdn_node( + cluster_id, + cdn_node_key0, + ).unwrap(); + + + // Add the 2nd cdn node to the Cluster + set_caller_value(manager_id, CONTRACT_FEE_LIMIT); + contract.cluster_add_cdn_node( + cluster_id, + cdn_node_key1, + ).unwrap(); + + + // Add the 3rd cdn node to the Cluster + set_caller_value(manager_id, CONTRACT_FEE_LIMIT); + contract.cluster_add_cdn_node( + cluster_id, + cdn_node_key2, + ).unwrap(); + + set_caller(manager_id); contract.cluster_reserve_resource(cluster_id, reserved_resource); @@ -161,6 +224,12 @@ fn new_cluster() -> TestCluster { node_key2 ]; + let cdn_nodes_keys = vec![ + cdn_node_key0, + cdn_node_key1, + cdn_node_key2 + ]; + let mut cluster_v_nodes = Vec::::new(); cluster_v_nodes.extend(v_nodes0.clone()); cluster_v_nodes.extend(v_nodes1.clone()); @@ -168,137 +237,40 @@ fn new_cluster() -> TestCluster { TestCluster { contract, - manager_id, - cluster_id, - cluster_params, + provider_id0, provider_id1, provider_id2, + node_key0, node_key1, node_key2, + node_params0, + node_params1, + node_params2, v_nodes0, v_nodes1, v_nodes2, + + cdn_node_key0, + cdn_node_key1, + cdn_node_key2, + cdn_node_params0, + cdn_node_params1, + cdn_node_params2, + + manager_id, + cluster_id, + cluster_params, cluster_v_nodes, rent_per_v_node, nodes_keys, - node_params0, - node_params1, - node_params2, + cdn_nodes_keys, capacity, reserved_resource, } } -// fn new_cluster_cdn() -> TestCluster { -// let accounts = get_accounts(); -// set_balance(accounts.charlie, 1000 * TOKEN); -// set_balance(accounts.django, 1000 * TOKEN); -// let provider_id0 = accounts.alice; -// let provider_id1 = accounts.bob; -// let provider_id2 = accounts.charlie; -// let manager_id = accounts.django; - -// let mut contract = setup(); - -// // Provide a Node. -// let rent_per_v_node: Balance = 10 * TOKEN; -// let node_params0 = "{\"url\":\"https://ddc.cere.network/bucket/{BUCKET_ID}\"}"; -// let capacity = 100; - -// for provider_id in [provider_id0, provider_id1, provider_id2] { -// set_caller_value(provider_id, CONTRACT_FEE_LIMIT); - -// contract.node_trust_manager(manager_id); -// let expected_perm = Permission::ClusterManagerTrustedBy(provider_id); -// assert!(contract.has_permission(manager_id, expected_perm)); -// } - -// set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); - -// let cdn_node_key0 = AccountId::from([0x0a; 32]); - -// let node_key0 = contract.cdn_node_create(cdn_node_key0, node_params0.to_string()); - -// // Provide another Node. -// let node_params1 = "{\"url\":\"https://ddc-1.cere.network/bucket/{BUCKET_ID}\"}"; -// set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); - -// let cdn_node_key1 = AccountId::from([0x0b; 32]); - -// let node_key1 = contract.cdn_node_create(cdn_node_key1, node_params1.to_string()); - -// // Provide another Node. -// let node_params2 = "{\"url\":\"https://ddc-2.cere.network/bucket/{BUCKET_ID}\"}"; -// set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); - -// let cdn_node_key2 = AccountId::from([0x0c; 32]); - -// let node_key2 = contract.cdn_node_create(cdn_node_key2, node_params2.to_string()); - -// // Create a Cluster. -// let _cluster_params = "{}"; - -// // TODO: adjust after cdn cluster topology and node addition - -// let vnodes = vec![1, 2, 3, 4, 5, 6]; - -// let node_keys = vec![node_key0, node_key1, node_key2]; -// let mut vnodes_wrapper = Vec::>::new(); -// vnodes_wrapper.push(vnodes); - -// let mut vnodes_wrapper = Vec::>::new(); - -// let vnodes_for_first_node = vec![1, 2, 3]; -// let vnodes_for_second_node = vec![4, 5, 6]; -// let vnodes_for_third_node = vec![7, 8, 9]; - -// vnodes_wrapper.push(vnodes_for_first_node); -// vnodes_wrapper.push(vnodes_for_second_node); -// vnodes_wrapper.push(vnodes_for_third_node); - -// set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - -// let cluster_id = contract.cdn_cluster_create( -// vec![ -// AccountId::from([0x0a; 32]), -// AccountId::from([0x0b; 32]), -// AccountId::from([0x0c; 32]) -// ] -// ); - -// let reserved = 10; - -// let mut vnodes = Vec::::new(); - -// for v_nodes_vec in vnodes_wrapper.clone() { -// for v_node in v_nodes_vec { -// vnodes.push(v_node.clone()); -// } -// } - -// TestCluster { -// contract, -// manager_id, -// cluster_id, -// provider_id0, -// provider_id1, -// provider_id2, -// node_key0, -// node_key1, -// node_key2, -// rent_per_v_node, -// vnodes_wrapper, -// node_params0, -// node_params1, -// node_params2, -// capacity, -// reserved, -// node_keys, -// vnodes, -// } -// } struct TestBucket { bucket_id: BucketId, @@ -307,14 +279,15 @@ struct TestBucket { } fn new_bucket(ctx: &mut TestCluster) -> TestBucket { - let accounts = get_accounts(); - let owner_id = accounts.django; + let owner_id = AccountId::from([0xd4, 0x8f, 0x63, 0x67, 0xe2, 0x15, 0x51, 0xdf, 0x11, 0x1c, 0x92, 0x69, 0x0d, 0x04, 0x3f, 0x75, 0xcb, 0x39, 0xf8, 0x27, 0xbb, 0xc7, 0x46, 0x4b, 0x8d, 0x5d, 0x70, 0xd1, 0x02, 0xaa, 0x71, 0x0a]); set_balance(owner_id, 1000 * TOKEN); set_caller_value(owner_id, CONTRACT_FEE_LIMIT); - let bucket_id = ctx - .contract - .bucket_create("{}".to_string(), ctx.cluster_id, None); + let bucket_id = ctx.contract.bucket_create( + "{}".to_string(), + ctx.cluster_id, + None + ); // Reserve some resources for the bucket from the cluster. set_caller_value(owner_id, CONTRACT_FEE_LIMIT); @@ -337,7 +310,9 @@ fn cluster_create_works() { let ctx = new_cluster(); let providers_ids = &[ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; let node_keys = &[ctx.node_key0, ctx.node_key1, ctx.node_key2]; + let cdn_node_keys = &[ctx.cdn_node_key0, ctx.cdn_node_key1, ctx.cdn_node_key2]; let node_params = &[ctx.node_params0.clone(), ctx.node_params1.clone(), ctx.node_params2.clone()]; + let cdn_node_params = &[ctx.cdn_node_params0.clone(), ctx.cdn_node_params1.clone(), ctx.cdn_node_params2.clone()]; assert_eq!(ctx.cluster_id, 0, "cluster_id must start at 0"); @@ -417,9 +392,8 @@ fn cluster_create_works() { cluster_params: ctx.cluster_params.clone(), revenues: Cash(0), total_rent: ctx.rent_per_v_node * ctx.cluster_v_nodes.len() as Balance, - cdn_nodes_keys: Vec::new(), + cdn_nodes_keys: ctx.cdn_nodes_keys, cdn_usd_per_gb: 104_857_600, - cdn_resources_used: 0, cdn_revenues: Cash(0), }, cluster_v_nodes @@ -431,7 +405,7 @@ fn cluster_create_works() { let mut events = get_events(); events.reverse(); // Work with pop(). - // Node created event + // Storage node created event for i in 0..3 { assert!(matches!(events.pop().unwrap(), Event::NodeCreated(ev) if ev == NodeCreated { @@ -443,6 +417,18 @@ fn cluster_create_works() { ); } + // CDN node created event + for i in 0..3 { + assert!(matches!(events.pop().unwrap(), Event::CdnNodeCreated(ev) if ev == + CdnNodeCreated { + cdn_node_key: cdn_node_keys[i], + provider_id: providers_ids[i], + cdn_node_params: cdn_node_params[i].clone(), + undistributed_payment: 0 + }) + ); + } + // Cluster created event assert!( matches!(events.pop().unwrap(), Event::ClusterCreated(ev) if ev == @@ -464,7 +450,7 @@ fn cluster_create_works() { ); } - // Cluster node added event + // Cluster storage node added event for i in 0..3 { assert!(matches!(events.pop().unwrap(), Event::ClusterNodeAdded(ev) if ev == ClusterNodeAdded { @@ -474,6 +460,16 @@ fn cluster_create_works() { ); } + // Cluster cdn node added event + for i in 0..3 { + assert!(matches!(events.pop().unwrap(), Event::ClusterCdnNodeAdded(ev) if ev == + ClusterCdnNodeAdded { + cluster_id: ctx.cluster_id, + cdn_node_key: cdn_node_keys[i] + }) + ); + } + // Cluster resource reserved event assert!( matches!(events.pop().unwrap(), Event::ClusterReserveResource(ev) if ev == @@ -608,6 +604,8 @@ fn cluster_management_validation_works() { let mut ctx = new_cluster(); let not_manager = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_manager, 1000 * TOKEN); + set_caller(not_manager); assert_eq!( ctx.contract.cluster_replace_node( @@ -634,127 +632,122 @@ fn cluster_management_validation_works() { } -// #[ink::test] -// fn cdn_cluster_gas_converter_works() { -// println!("Creating new cdn cluster"); +#[ink::test] +fn cdn_cluster_gas_converter_works() { + println!("Creating new cdn cluster"); -// let mut ctx = new_cluster_cdn(); + let mut ctx = new_cluster(); -// println!("Got cdn cluster back"); -// // The provider stops trusting the manager_id. -// println!("Cdn cluster id is {}", ctx.cluster_id); -// set_caller(ctx.manager_id); -// ctx.contract.cdn_set_rate(ctx.cluster_id, 3_750_000_000); -// set_caller(ctx.provider_id0); -// let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); + // The provider stops trusting the manager_id. + println!("Cdn cluster id is {}", ctx.cluster_id); + set_caller(ctx.manager_id); + ctx.contract.cdn_set_rate(ctx.cluster_id, 3_750_000_000); + set_caller(ctx.provider_id0); + let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); -// let usd_per_cere = TOKEN / 100; -// set_caller(ctx.provider_id0); -// ctx.contract.account_set_usd_per_cere(usd_per_cere); + let usd_per_cere = TOKEN / 100; + set_caller(admin_id()); + ctx.contract.account_set_usd_per_cere(usd_per_cere); -// let usd_amount = ctx.contract.account_get_usd_per_cere(); -// println!("Current usd amount is {}", usd_amount); + let usd_amount = ctx.contract.account_get_usd_per_cere(); + println!("Current usd amount is {}", usd_amount); -// println!("The current rate is {}", rate); + println!("The current rate is {}", rate); -// let usd_per_kb = rate / KB_PER_GB; -// println!("The current rate per kb {}", usd_per_kb); + let usd_per_kb = rate / KB_PER_GB; + println!("The current rate per kb {}", usd_per_kb); -// let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); -// println!("The current cere rate per kb {}", cere_per_kb); -// } + let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); + println!("The current cere rate per kb {}", cere_per_kb); +} -// #[ink::test] -// fn cdn_cluster_payment_works() { -// println!("Creating new cdn cluster"); -// let mut ctx = new_cluster_cdn(); +#[ink::test] +fn cdn_cluster_payment_works() { + // todo: this test scenario must be revised as it does pure printing without any assertion + println!("Creating new cdn cluster"); -// println!("Got cdn cluster back"); -// // The provider stops trusting the manager_id. -// println!("Cdn cluster id is {}", ctx.cluster_id); -// set_caller(ctx.provider_id0); -// let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); + let mut ctx = new_cluster(); + + // The provider stops trusting the manager_id. + println!("Cluster id is {}", ctx.cluster_id); + set_caller(ctx.provider_id0); -// let usd_per_cere = TOKEN / 100; -// set_caller(ctx.provider_id0); -// ctx.contract.account_set_usd_per_cere(usd_per_cere); + let usd_per_cere = TOKEN / 100; + set_caller(admin_id()); + ctx.contract.account_set_usd_per_cere(usd_per_cere); -// let usd_amount = ctx.contract.account_get_usd_per_cere(); -// println!("Current usd amount is {}", usd_amount); + let usd_amount = ctx.contract.account_get_usd_per_cere(); + println!("Current usd amount is {}", usd_amount); -// println!("The current rate is {}", rate); + let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); + println!("The current rate is {}", rate); -// let usd_per_kb = rate / KB_PER_GB; -// println!("The current rate per kb {}", usd_per_kb); + let usd_per_kb = rate / KB_PER_GB; + println!("The current rate per kb {}", usd_per_kb); -// let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); -// println!("The current cere rate per kb {}", cere_per_kb); + let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); + println!("The current cere rate per kb {}", cere_per_kb); -// set_caller_value(ctx.provider_id0, 10 * TOKEN); -// ctx.contract.account_deposit(); + set_caller_value(ctx.provider_id0, 10 * TOKEN); + ctx.contract.account_deposit(); -// set_caller(ctx.provider_id0); -// ctx.contract.account_bond(5 * TOKEN); + set_caller_value(ctx.provider_id0, 10 * TOKEN); + ctx.contract.account_bond(5 * TOKEN); -// set_caller(ctx.provider_id0); -// ctx.contract.set_fee_bp(1_000); + set_caller(ctx.provider_id0); + ctx.contract.set_fee_bp(1_000); -// let mut account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); -// println!("{:?}", account); + let account0_before_putting = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); + println!("Before putting revenue: {:?}", account0_before_putting); -// ctx.contract.cdn_cluster_put_revenue( -// ctx.cluster_id, -// vec![(ctx.provider_id0, 1000), (ctx.provider_id0, 541643)], -// vec![(ctx.node_key0, 1000), (ctx.node_key1, 541643)], -// vec![], -// 5, -// ); -// account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); -// println!("{:?}", account); + ctx.contract.cdn_cluster_put_revenue( + ctx.cluster_id, + vec![(ctx.provider_id0, 1000), (ctx.provider_id0, 541643)], + vec![(ctx.cdn_node_key0, 1000), (ctx.cdn_node_key1, 541643)], + vec![], + 5, + ); + let account0_after_putting = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); + println!("After putting revenue: {:?}", account0_after_putting); -// let cdn_cluster_list_one = ctx.contract.cdn_cluster_list(0, 10, None); -// print!("Cluster list one {:?}", cdn_cluster_list_one); -// let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); -// let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); + let cluster_list_1 = ctx.contract.cluster_list(0, 10, None); + println!("Cluster list one {:?}", cluster_list_1); + let cdn_node0 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key0).unwrap(); + let cdn_node1 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key1).unwrap(); -// println!("Node 1 {:?}", node0); -// println!("Node 2 {:?}", node1); -// // let cdn_cluster0 = ctx.contract.cdn_clusters.get(ctx.cluster_id); -// // print!("{:?}", cdn_cluster0); -// // let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); -// // print!("{:?}", cdn_cluster0); -// // print!("{:?}", cdn_cluster_list); + println!("{:?}", cdn_node0); + println!("{:?}", cdn_node1); + let cluster0 = ctx.contract.clusters.get(ctx.cluster_id); + println!("{:?}", cluster0); + let cluster_list = ctx.contract.cluster_list(0, 10, None); + println!("{:?}", cluster0); + println!("{:?}", cluster_list); -// let validated_commit_node0 = ctx.contract.get_validated_commit(ctx.node_key0); -// print!("Validated commit {:?}", validated_commit_node0); + let validated_commit_node0 = ctx.contract.get_validated_commit(ctx.cdn_node_key0); + println!("Validated commit: {:?}", validated_commit_node0); -// let fee = ctx.contract.get_fee_bp(); -// print!("Protocol fee in basis points {:?}", fee); + let fee = ctx.contract.get_fee_bp(); + println!("Protocol fee in basis points: {:?}", fee); -// let protocol_revenues = ctx.contract.get_protocol_revenues(); -// print!("Protocol revenues are {:?}", protocol_revenues); + let protocol_revenues = ctx.contract.get_protocol_revenues(); + println!("Protocol revenues: {:?}", protocol_revenues); -// set_caller(ctx.provider_id0); -// ctx.contract.cdn_cluster_distribute_revenues(0); + set_caller(ctx.provider_id0); + ctx.contract.cdn_cluster_distribute_revenues(ctx.cluster_id); -// let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); -// let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); -// println!("{:?}", node0); -// println!("{:?}", node1); + let cdn_node0 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key0).unwrap(); + let cdn_node1 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key1).unwrap(); + println!("{:?}", cdn_node0); + println!("{:?}", cdn_node1); -// let cdn_cluster_list = ctx.contract.cdn_cluster_list(0, 10, None); -// print!("{:?}", cdn_cluster_list); + let cdn_cluster_list = ctx.contract.cluster_list(0, 10, None); + println!("{:?}", cdn_cluster_list); -// account = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); -// // let node0 = ctx.contract.cdn_nodes.get(ctx.node_key0).unwrap(); -// // let node1 = ctx.contract.cdn_nodes.get(ctx.node_key1).unwrap(); -// println!("{:?}", account); -// // let account1 = ctx.contract.accounts.get(&ctx.provider_id1).unwrap(); -// // println!("{:?}", account1); -// // let account_balance = ink_env::balance(&ctx.provider_id0); -// // println!("{:?}", account_balance); -// } + let account0_after_distributing = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); + println!("{:?}", account0_after_distributing); + +} fn bucket_settle_payment(ctx: &mut TestCluster, test_bucket: &TestBucket) { // Go to the future when some revenues are due. @@ -920,103 +913,107 @@ fn cluster_add_node_works() { } +#[ink::test] +fn cluster_pays_providers() { + let ctx = &mut new_cluster(); + let test_bucket = &new_bucket(ctx); + bucket_settle_payment(ctx, &test_bucket); + + // Get state before the distribution. + let to_distribute = ctx + .contract + .cluster_get(ctx.cluster_id)? + .cluster + .revenues + .peek(); + + let before0 = balance_of(ctx.provider_id0); + let before1 = balance_of(ctx.provider_id1); + let before2 = balance_of(ctx.provider_id2); + let before_mgmt = balance_of(ctx.manager_id); + + let skip_events = get_events::().len(); + + // Set a network fee. + let network_fee_bp = 100; // 1% + let cluster_management_fee_bp = 200; // 2% + set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); + ctx.contract.admin_set_fee_config(FeeConfig { + network_fee_bp, + network_fee_destination: AccountId::default(), + cluster_management_fee_bp, + }); + + let burned_fee = to_distribute * network_fee_bp / 10_000; + let manager_fee = (to_distribute - burned_fee) * cluster_management_fee_bp / 10_000; + let provider_fee: u128 = (to_distribute - burned_fee - manager_fee) / 3; + + // Distribute the revenues of the cluster to providers. + ctx.contract.cluster_distribute_revenues(ctx.cluster_id); + + // Check the last events. + let mut events = get_events(); + events.reverse(); // Work with pop(). + events.truncate(events.len() - skip_events); + let expected_recipients = vec![ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; + + for provider_id in expected_recipients { + assert!( + matches!(events.pop().unwrap(), Event::ClusterDistributeRevenues(ev) if ev == + ClusterDistributeRevenues { + cluster_id: ctx.cluster_id, + provider_id + }) + ); + } + + assert_eq!(events.len(), 0, "all events must be checked"); + + // Get state after the distribution. + let rounding_error = ctx + .contract + .cluster_get(ctx.cluster_id)? + .cluster + .revenues + .peek(); + + let earned0 = balance_of(ctx.provider_id0) - before0; + let earned1 = balance_of(ctx.provider_id1) - before1; + let earned2 = balance_of(ctx.provider_id2) - before2; + let earned_mgmt = balance_of(ctx.manager_id) - before_mgmt; + + assert!(provider_fee > 0, "provider must earn something"); + assert_eq!( + earned0, provider_fee, + "providers must earn the correct amount" + ); + assert_eq!( + earned1, provider_fee, + "providers must earn the correct amount" + ); + assert_eq!( + earned2, provider_fee, + "providers must earn the correct amount" + ); + + assert!(burned_fee > 0, "the network must earn something"); + assert!(manager_fee > 0, "the manager_id must earn something"); + assert_eq!( + earned_mgmt, manager_fee, + "the manager_id must earn the correct amount" + ); -// #[ink::test] -// fn cluster_pays_providers() { -// let ctx = &mut new_cluster(); -// let test_bucket = &new_bucket(ctx); -// bucket_settle_payment(ctx, &test_bucket); - -// // Get state before the distribution. -// let to_distribute = ctx -// .contract -// .cluster_get(ctx.cluster_id)? -// .cluster -// .revenues -// .peek(); -// let before0 = balance_of(ctx.provider_id0); -// let before1 = balance_of(ctx.provider_id1); -// let before2 = balance_of(ctx.provider_id2); -// let before_mgmt = balance_of(ctx.manager_id); - -// let skip_events = get_events::().len(); - -// // Set a network fee. -// let network_fee_bp = 100; // 1% -// let cluster_management_fee_bp = 200; // 2% -// set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); -// ctx.contract.admin_set_fee_config(FeeConfig { -// network_fee_bp, -// network_fee_destination: AccountId::default(), -// cluster_management_fee_bp, -// }); - -// let burned_fee = to_distribute * network_fee_bp / 10_000; -// let manager_fee = (to_distribute - burned_fee) * cluster_management_fee_bp / 10_000; -// let provider_fee = (to_distribute - burned_fee - manager_fee) / 3; - -// // Distribute the revenues of the cluster to providers. -// ctx.contract.cluster_distribute_revenues(ctx.cluster_id); - -// // Check the last events. -// let mut events = get_events(); -// events.reverse(); // Work with pop(). -// events.truncate(events.len() - skip_events); -// let expected_recipients = vec![ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; - -// for provider_id in expected_recipients { -// assert!( -// matches!(events.pop().unwrap(), Event::ClusterDistributeRevenues(ev) if ev == -// ClusterDistributeRevenues { cluster_id: ctx.cluster_id, provider_id }) -// ); -// } - -// assert_eq!(events.len(), 0, "all events must be checked"); - -// // Get state after the distribution. -// let rounding_error = ctx -// .contract -// .cluster_get(ctx.cluster_id)? -// .cluster -// .revenues -// .peek(); -// let earned0 = balance_of(ctx.provider_id0) - before0; -// let earned1 = balance_of(ctx.provider_id1) - before1; -// let earned2 = balance_of(ctx.provider_id2) - before2; -// let earned_mgmt = balance_of(ctx.manager_id) - before_mgmt; - -// assert!(provider_fee > 0, "provider must earn something"); -// assert_eq!( -// earned0, provider_fee, -// "providers must earn the correct amount" -// ); -// assert_eq!( -// earned1, provider_fee, -// "providers must earn the correct amount" -// ); -// assert_eq!( -// earned2, provider_fee, -// "providers must earn the correct amount" -// ); - -// assert!(burned_fee > 0, "the network must earn something"); -// assert!(manager_fee > 0, "the manager_id must earn something"); -// assert_eq!( -// earned_mgmt, manager_fee, -// "the manager_id must earn the correct amount" -// ); - -// assert!(to_distribute > 0); -// assert!( -// rounding_error < 10, -// "revenues must go out of the cluster (besides rounding)" -// ); -// assert_eq!( -// earned0 + earned1 + earned2 + burned_fee + manager_fee + rounding_error, -// to_distribute, -// "all revenues must go to providers" -// ); -// } + assert!(to_distribute > 0); + assert!( + rounding_error < 10, + "revenues must go out of the cluster (besides rounding)" + ); + assert_eq!( + earned0 + earned1 + earned2 + burned_fee + manager_fee + rounding_error, + to_distribute, + "all revenues must go to providers" + ); +} #[ink::test] @@ -1076,10 +1073,11 @@ fn bucket_create_works() { } - #[ink::test] fn account_deposit_works() { - let account_id = get_accounts().alice; + let account_id = AccountId::from([0x76, 0x95, 0x7c, 0xa6, 0xbe, 0xf5, 0xa3, 0x6d, 0x67, 0x0d, 0x3a, 0x84, 0xc6, 0x0a, 0xe2, 0xbb, 0xc9, 0x5e, 0xee, 0xde, 0x3a, 0x5f, 0x27, 0x0e, 0x26, 0xe3, 0x43, 0x4c, 0x46, 0xe2, 0x98, 0x10]); + set_balance(account_id, 1000 * TOKEN); + let mut contract = setup(); assert_eq!( @@ -1162,6 +1160,7 @@ fn node_set_params_only_owner() { let mut ctx = new_cluster(); let not_provider = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_provider, 1000 * TOKEN); // Change params.not_provider let new_node_params = NodeParams::from("new node params"); set_caller_value(not_provider, CONTRACT_FEE_LIMIT); @@ -1194,6 +1193,7 @@ fn cluster_change_params_only_owner() { let ctx = &mut new_cluster(); let not_manager = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_manager, 1000 * TOKEN); // Change params. let new_cluster_params = NodeParams::from("new cluster params"); set_caller_value(not_manager, CONTRACT_FEE_LIMIT); @@ -1235,81 +1235,84 @@ fn bucket_change_params_only_owner() { // Panic. } -// #[ink::test] -// fn bucket_list_works() { -// let mut ddc_bucket = setup(); -// let accounts = get_accounts(); -// let owner_id1 = accounts.alice; -// let owner_id2 = accounts.bob; -// let owner_id3 = accounts.charlie; -// let cluster_id = 0; - -// set_caller_value(owner_id1, CONTRACT_FEE_LIMIT); -// let bucket_id1 = ddc_bucket.bucket_create("".to_string(), cluster_id, None); -// let bucket_status1 = ddc_bucket.bucket_get(bucket_id1).unwrap(); - -// set_caller_value(owner_id2, CONTRACT_FEE_LIMIT); -// let bucket_id2 = ddc_bucket.bucket_create("".to_string(), cluster_id, None); -// let bucket_status2 = ddc_bucket.bucket_get(bucket_id2)?; - -// assert_ne!(bucket_id1, bucket_id2); -// let count = 3; - -// assert_eq!( -// ddc_bucket.bucket_list(1, 100, None), -// (vec![bucket_status1.clone(), bucket_status2.clone()], count) -// ); - -// assert_eq!( -// ddc_bucket.bucket_list(1, 2, None), -// (vec![bucket_status1.clone(), bucket_status2.clone()], count) -// ); - -// assert_eq!( -// ddc_bucket.bucket_list(1, 1, None), -// ( -// vec![bucket_status1.clone() /*, bucket_status2.clone()*/], -// count -// ) -// ); -// assert_eq!( -// ddc_bucket.bucket_list(2, 1, None), -// ( -// vec![/*bucket_status1.clone(),*/ bucket_status2.clone()], -// count -// ) -// ); - -// assert_eq!(ddc_bucket.bucket_list(count, 20, None), (vec![], count)); - -// // Filter by owner. -// assert_eq!( -// ddc_bucket.bucket_list(1, 100, Some(owner_id1)), -// ( -// vec![bucket_status1.clone() /*, bucket_status2.clone()*/], -// count -// ) -// ); - -// assert_eq!( -// ddc_bucket.bucket_list(1, 100, Some(owner_id2)), -// ( -// vec![/*bucket_status1.clone(),*/ bucket_status2.clone()], -// count -// ) -// ); - -// assert_eq!( -// ddc_bucket.bucket_list(1, 100, Some(owner_id3)), -// (vec![], count) -// ); -// } +#[ink::test] +fn bucket_list_works() { + let mut ddc_bucket = setup(); + + let owner_id1 = AccountId::from([0xd8, 0x69, 0x19, 0x54, 0xea, 0xdc, 0x9a, 0xc0, 0x3d, 0x37, 0x56, 0x9f, 0x2a, 0xe8, 0xdf, 0x59, 0x34, 0x3f, 0x32, 0x65, 0xba, 0xd4, 0x16, 0xac, 0x07, 0xdf, 0x06, 0xeb, 0x4d, 0xbc, 0x6a, 0x66]); + set_balance(owner_id1, 1000 * TOKEN); + let owner_id2 = AccountId::from([0x2a, 0x5f, 0xbc, 0xcf, 0x71, 0x0b, 0x65, 0x04, 0x88, 0x91, 0x12, 0x7e, 0x5e, 0xe3, 0x78, 0xdb, 0x48, 0x63, 0x09, 0x44, 0xcc, 0xc5, 0x75, 0xbd, 0xa5, 0xaa, 0xa5, 0x0e, 0x77, 0xab, 0x7b, 0x4e]); + set_balance(owner_id2, 1000 * TOKEN); + let owner_id3 = AccountId::from([0x64, 0xef, 0xd7, 0xb4, 0x41, 0xb2, 0x58, 0xb5, 0x56, 0x6b, 0xfc, 0x4b, 0x19, 0xb8, 0xe5, 0x09, 0x5d, 0x17, 0xb3, 0xc3, 0x44, 0x38, 0x58, 0xa9, 0x7d, 0x20, 0x49, 0x39, 0xbd, 0xbd, 0xb6, 0x48]); + set_balance(owner_id3, 1000 * TOKEN); + + let cluster_id = 0; + + set_caller_value(owner_id1, CONTRACT_FEE_LIMIT); + let bucket_id1 = ddc_bucket.bucket_create("".to_string(), cluster_id, None); + let bucket_status1 = ddc_bucket.bucket_get(bucket_id1).unwrap(); + set_caller_value(owner_id2, CONTRACT_FEE_LIMIT); + let bucket_id2 = ddc_bucket.bucket_create("".to_string(), cluster_id, None); + let bucket_status2 = ddc_bucket.bucket_get(bucket_id2)?; + + assert_ne!(bucket_id1, bucket_id2); + let count = 2; + + assert_eq!( + ddc_bucket.bucket_list(0, 100, None), + (vec![bucket_status1.clone(), bucket_status2.clone()], count) + ); + + assert_eq!( + ddc_bucket.bucket_list(0, 2, None), + (vec![bucket_status1.clone(), bucket_status2.clone()], count) + ); + + assert_eq!( + ddc_bucket.bucket_list(0, 1, None), + ( + vec![bucket_status1.clone()], + count + ) + ); + assert_eq!( + ddc_bucket.bucket_list(1, 1, None), + ( + vec![bucket_status2.clone()], + count + ) + ); + + assert_eq!(ddc_bucket.bucket_list(count, 20, None), (vec![], count)); + + // Filter by owner. + assert_eq!( + ddc_bucket.bucket_list(0, 100, Some(owner_id1)), + ( + vec![bucket_status1.clone()], + count + ) + ); + + assert_eq!( + ddc_bucket.bucket_list(0, 100, Some(owner_id2)), + ( + vec![bucket_status2.clone()], + count + ) + ); + + assert_eq!( + ddc_bucket.bucket_list(0, 100, Some(owner_id3)), + (vec![], count) + ); +} #[ink::test] fn node_list_works() { - let mut ctx = new_cluster(); + let ctx = new_cluster(); let node_info = ctx.contract.node_get(ctx.node_key1)?; assert_eq!(ctx.provider_id1, node_info.node.provider_id.clone()); @@ -1340,44 +1343,45 @@ fn node_list_works() { v_nodes: ctx.v_nodes2.clone() }; + let count = 3; + assert_eq!( ctx.contract.node_list(1, 100, None), - (vec![node1.clone(), node2.clone()], 3) + (vec![node1.clone(), node2.clone()], count) ); assert_eq!( ctx.contract.node_list(1, 2, None), - (vec![node1.clone(), node2.clone()], 3) + (vec![node1.clone(), node2.clone()], count) ); assert_eq!( ctx.contract.node_list(1, 1, None), - (vec![node1.clone() /*, node2.clone()*/], 3) + (vec![node1.clone() /*, node2.clone()*/], count) ); assert_eq!( ctx.contract.node_list(2, 1, None), - (vec![/*node1.clone(),*/ node2.clone()], 3) + (vec![/*node1.clone(),*/ node2.clone()], count) ); - assert_eq!(ctx.contract.node_list(21, 20, None), (vec![], 3)); + assert_eq!(ctx.contract.node_list(21, 20, None), (vec![], count)); // Filter by owner. assert_eq!( ctx.contract.node_list(1, 100, Some(ctx.provider_id1)), - (vec![node1.clone() /*, node2.clone()*/], 3) + (vec![node1.clone() /*, node2.clone()*/], count) ); assert_eq!( ctx.contract.node_list(1, 100, Some(ctx.provider_id2)), - (vec![/*node1.clone(),*/ node2.clone()], 3) + (vec![/*node1.clone(),*/ node2.clone()], count) ); let not_provider= AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); - assert_eq!( ctx.contract.node_list(1, 100, Some(not_provider)), - (vec![], 3) + (vec![], count) ); } diff --git a/bucket/ddc_bucket/tests/test_currency.rs b/bucket/ddc_bucket/tests/test_currency.rs index e64c5fef..91e7e5eb 100644 --- a/bucket/ddc_bucket/tests/test_currency.rs +++ b/bucket/ddc_bucket/tests/test_currency.rs @@ -9,7 +9,7 @@ fn setup() -> DdcBucket { set_callee(contract_id()); let mut contract = DdcBucket::new(); set_balance(contract_id(), CONTRACT_FEE_LIMIT); - contract.admin_grant_permission(admin_id(), Permission::SetExchangeRate); + contract.admin_grant_permission(admin_id(), Permission::SetExchangeRate).unwrap(); contract } From 1bf1a4e00bef03a2fe03dc85ab85c7813f6b128a Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 28 Jun 2023 16:17:31 +0200 Subject: [PATCH 42/89] chore(test): tests for admin operations are recovered --- bucket/ddc_bucket/tests/test_admin.rs | 177 ++++++++++++++------------ 1 file changed, 94 insertions(+), 83 deletions(-) diff --git a/bucket/ddc_bucket/tests/test_admin.rs b/bucket/ddc_bucket/tests/test_admin.rs index 76d0383f..87e25acb 100644 --- a/bucket/ddc_bucket/tests/test_admin.rs +++ b/bucket/ddc_bucket/tests/test_admin.rs @@ -1,118 +1,129 @@ -// use ink_lang as ink; +use ink_lang as ink; -// use crate::ddc_bucket::*; +use crate::ddc_bucket::*; +use crate::ddc_bucket::Error::*; -// use super::env_utils::*; +use super::env_utils::*; -// #[ink::test] -// fn admin_init_works() { -// let contract = setup(); +#[ink::test] +fn admin_init_works() { + let contract = setup(); -// // The deployer is SuperAdmin. -// assert!(contract.has_permission(admin_id(), Permission::SuperAdmin)); -// assert!(!contract.has_permission(not_admin_id(), Permission::SuperAdmin)); + // The deployer is SuperAdmin. + assert!(contract.has_permission(admin_id(), Permission::SuperAdmin)); + assert!(!contract.has_permission(not_admin_id(), Permission::SuperAdmin)); -// // The SuperAdmin has all other permissions, too. -// assert!(contract.has_permission(admin_id(), Permission::SetExchangeRate)); -// assert!(!contract.has_permission(not_admin_id(), Permission::SetExchangeRate)); -// } + // The SuperAdmin has all other permissions, too. + assert!(contract.has_permission(admin_id(), Permission::SetExchangeRate)); + assert!(!contract.has_permission(not_admin_id(), Permission::SetExchangeRate)); +} -// #[ink::test] -// fn admin_withdraw_works() { -// let mut contract = setup(); -// assert_eq!(balance_of(contract_id()), 10); +#[ink::test] +fn admin_withdraw_works() { + let mut contract = setup(); + assert_eq!(balance_of(contract_id()), 10); -// set_caller(admin_id()); + set_caller(admin_id()); -// contract.admin_withdraw(9); + contract.admin_withdraw(9); -// assert_eq!(balance_of(contract_id()), 1); -// } + assert_eq!(balance_of(contract_id()), 1); +} -// #[ink::test] -// #[should_panic] -// fn admin_withdraw_only_admin() { -// let mut contract = setup(); +#[ink::test] +#[should_panic] +fn admin_withdraw_only_admin() { + let mut contract = setup(); -// set_caller(not_admin_id()); + set_caller(not_admin_id()); -// contract.admin_withdraw(9); // panic. -// } + contract.admin_withdraw(9); // panic. +} -// #[ink::test] -// fn admin_grant_works() { -// let mut contract = setup(); -// let permission = Permission::SuperAdmin; +#[ink::test] +fn admin_grant_works() { + let mut contract = setup(); + let permission = Permission::SuperAdmin; -// set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); + set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); -// let new_admin_id = not_admin_id(); + let new_admin_id = not_admin_id(); -// contract.admin_grant_permission(new_admin_id, permission); + contract.admin_grant_permission(new_admin_id, permission); -// // Check the last event. -// let ev = get_events().pop().unwrap(); -// assert!(matches!(ev, Event::PermissionGranted(ev) if ev == -// PermissionGranted { account_id: not_admin_id(), permission })); + // Check the last event. + let ev = get_events().pop().unwrap(); + assert!(matches!(ev, Event::PermissionGranted(ev) if ev == + PermissionGranted { account_id: not_admin_id(), permission })); -// assert!(contract.has_permission(new_admin_id, permission)); + assert!(contract.has_permission(new_admin_id, permission)); -// set_caller(new_admin_id); + set_caller(new_admin_id); -// contract.admin_withdraw(9); -// } + contract.admin_withdraw(9); +} -// #[ink::test] -// #[should_panic] -// fn admin_grant_only_admin() { -// let mut contract = setup(); +#[ink::test] +fn admin_grant_only_admin() { + let mut contract = setup(); -// set_caller_value(not_admin_id(), CONTRACT_FEE_LIMIT); + set_caller_value(not_admin_id(), CONTRACT_FEE_LIMIT); -// contract.admin_grant_permission(get_accounts().charlie, Permission::SuperAdmin); // panic. -// } + assert_eq!( + contract.admin_grant_permission( + get_accounts().charlie, + Permission::SuperAdmin + ), + Err(OnlySuperAdmin) + ); +} -// #[ink::test] -// #[should_panic] -// fn admin_revoke_works() { -// let mut contract = setup(); -// let permission = Permission::SuperAdmin; +#[ink::test] +#[should_panic] +fn admin_revoke_works() { + let mut contract = setup(); + let permission = Permission::SuperAdmin; -// set_caller(admin_id()); + set_caller(admin_id()); -// contract.admin_revoke_permission(admin_id(), permission); + contract.admin_revoke_permission(admin_id(), permission); -// // Check the last event. -// let ev = get_events().pop().unwrap(); -// assert!(matches!(ev, Event::PermissionRevoked(ev) if ev == -// PermissionRevoked { account_id: not_admin_id(), permission })); + // Check the last event. + let ev = get_events().pop().unwrap(); + assert!(matches!(ev, Event::PermissionRevoked(ev) if ev == + PermissionRevoked { account_id: not_admin_id(), permission })); -// assert!(!contract.has_permission(admin_id(), permission)); + assert!(!contract.has_permission(admin_id(), permission)); -// // Cannot withdraw because no more permission. -// set_caller(admin_id()); + // Cannot withdraw because no more permission. + set_caller(admin_id()); -// contract.admin_withdraw(9); // panic. -// } + contract.admin_withdraw(9); // panic. +} -// #[ink::test] -// #[should_panic] -// fn admin_revoke_only_admin() { -// let mut contract = setup(); +#[ink::test] +fn admin_revoke_only_admin() { + let mut contract = setup(); -// set_caller_value(not_admin_id(), CONTRACT_FEE_LIMIT); + set_caller_value(not_admin_id(), CONTRACT_FEE_LIMIT); -// contract.admin_revoke_permission(admin_id(), Permission::SuperAdmin); // panic. -// } + assert_eq!( + contract.admin_revoke_permission( + admin_id(), + Permission::SuperAdmin + ), + Err(OnlySuperAdmin) + ); +} -// fn setup() -> DdcBucket { -// set_caller(admin_id()); -// set_callee(contract_id()); -// let contract = DdcBucket::new(); -// set_balance(contract_id(), 10); -// contract -// } +fn setup() -> DdcBucket { + set_caller(admin_id()); + set_callee(contract_id()); + let contract = DdcBucket::new(); + set_balance(contract_id(), 10); + contract +} -// fn not_admin_id() -> AccountId { -// get_accounts().bob -// } \ No newline at end of file +fn not_admin_id() -> AccountId { + get_accounts().bob +} \ No newline at end of file From 7d9a9e9bf56bb1e5fddc70d154685c9cded847a1 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 28 Jun 2023 16:45:33 +0200 Subject: [PATCH 43/89] chore(node): only_owner call is renamed to only_provider --- bucket/ddc_bucket/admin.rs | 4 ++-- bucket/ddc_bucket/cdn_node/entity.rs | 2 +- bucket/ddc_bucket/cdn_node/messages.rs | 4 ++-- bucket/ddc_bucket/cluster/messages.rs | 4 ++-- bucket/ddc_bucket/node/entity.rs | 2 +- bucket/ddc_bucket/node/messages.rs | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bucket/ddc_bucket/admin.rs b/bucket/ddc_bucket/admin.rs index a40aee0c..f1041c38 100644 --- a/bucket/ddc_bucket/admin.rs +++ b/bucket/ddc_bucket/admin.rs @@ -58,7 +58,7 @@ impl DdcBucket { let mut node = self.nodes.get(node_key)?; // allow node ownership transfer only if the current owner is the admin - node.only_owner(admin).map_err(|_| NodeOwnerIsNotSuperAdmin)?; + node.only_provider(admin).map_err(|_| NodeOwnerIsNotSuperAdmin)?; node.provider_id = new_owner; self.nodes.update(node_key, &node)?; @@ -82,7 +82,7 @@ impl DdcBucket { let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; // allow node ownership transfer only if the current owner is the admin - cdn_node.only_owner(admin).map_err(|_| CdnNodeOwnerIsNotSuperAdmin)?; + cdn_node.only_provider(admin).map_err(|_| CdnNodeOwnerIsNotSuperAdmin)?; cdn_node.provider_id = new_owner; self.cdn_nodes.update(cdn_node_key, &cdn_node)?; diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index a14124da..bca68fad 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -57,7 +57,7 @@ impl CdnNode { Ok(cdn_node) } - pub fn only_owner(&self, caller: AccountId) -> Result<()> { + pub fn only_provider(&self, caller: AccountId) -> Result<()> { (self.provider_id == caller) .then(|| ()) .ok_or(OnlyCdnNodeOwner) diff --git a/bucket/ddc_bucket/cdn_node/messages.rs b/bucket/ddc_bucket/cdn_node/messages.rs index a021c729..84de2e76 100644 --- a/bucket/ddc_bucket/cdn_node/messages.rs +++ b/bucket/ddc_bucket/cdn_node/messages.rs @@ -41,7 +41,7 @@ impl DdcBucket { let caller = Self::env().caller(); let cdn_node = self.cdn_nodes.get(cdn_node_key)?; - cdn_node.only_owner(caller)?; + cdn_node.only_provider(caller)?; cdn_node.only_without_cluster()?; self.cdn_nodes.remove(cdn_node_key); @@ -61,7 +61,7 @@ impl DdcBucket { let caller = Self::env().caller(); let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; - cdn_node.only_owner(caller)?; + cdn_node.only_provider(caller)?; cdn_node.set_params(cdn_node_params.clone())?; self.cdn_nodes.update(cdn_node_key, &cdn_node)?; diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 6e92f324..81567dce 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -94,7 +94,7 @@ impl DdcBucket { node.only_with_cluster(cluster_id)?; if !cluster.only_manager(caller).is_ok() - && !node.only_owner(caller).is_ok() { + && !node.only_provider(caller).is_ok() { return Err(OnlyClusterManagerOrNodeOwner); } @@ -201,7 +201,7 @@ impl DdcBucket { cdn_node.only_with_cluster(cluster_id)?; if !cluster.only_manager(caller).is_ok() - && !cdn_node.only_owner(caller).is_ok() { + && !cdn_node.only_provider(caller).is_ok() { return Err(OnlyClusterManagerOrCdnNodeOwner); } diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index 134ecdaa..d8f8db09 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -87,7 +87,7 @@ impl Node { Ok(node) } - pub fn only_owner(&self, caller: AccountId) -> Result<()> { + pub fn only_provider(&self, caller: AccountId) -> Result<()> { (self.provider_id == caller) .then(|| ()) .ok_or(OnlyNodeOwner) diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index 0ac510ea..7136e43a 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -42,7 +42,7 @@ impl DdcBucket { let caller = Self::env().caller(); let node = self.nodes.get(node_key)?; - node.only_owner(caller)?; + node.only_provider(caller)?; node.only_without_cluster()?; self.nodes.remove(node_key); @@ -62,7 +62,7 @@ impl DdcBucket { let caller = Self::env().caller(); let mut node = self.nodes.get(node_key)?; - node.only_owner(caller)?; + node.only_provider(caller)?; node.set_params(node_params.clone())?; self.nodes.update(node_key, &node)?; From 8e59e94360353bbceeccd85aaf82bc1dc519ac6c Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 28 Jun 2023 17:00:22 +0200 Subject: [PATCH 44/89] chore(cluster): calls for distributing revenues renamed --- bucket/ddc_bucket/cluster/messages.rs | 5 ++--- bucket/ddc_bucket/tests/test_contract.rs | 5 +++-- bucket/lib.rs | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 81567dce..83b41f7e 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -481,7 +481,7 @@ impl DdcBucket { // First payment is for aggregate consumption for account, second is the aggregate payment for the node (u32 for ids) - pub fn message_cdn_cluster_put_revenue( + pub fn message_cluster_put_cdn_revenue( &mut self, cluster_id: ClusterId, aggregates_accounts: Vec<(AccountId, u128)>, @@ -490,7 +490,6 @@ impl DdcBucket { era: u64 ) -> Result<()> { let mut cluster = self.clusters.get(cluster_id)?; - // Self::only_cdn_cluster_manager(cluster)?; let mut cluster_payment = 0; let mut _undistributed_payment_accounts = 0; @@ -556,7 +555,7 @@ impl DdcBucket { } - pub fn message_cdn_cluster_distribute_revenues(&mut self, cluster_id: ClusterId) -> Result<()> { + pub fn message_cluster_distribute_cdn_revenue(&mut self, cluster_id: ClusterId) -> Result<()> { let mut cluster = self.clusters.get(cluster_id)?; // Charge the network fee from the cluster. diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index 5a33b830..58e78b2e 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -701,7 +701,7 @@ fn cdn_cluster_payment_works() { let account0_before_putting = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); println!("Before putting revenue: {:?}", account0_before_putting); - ctx.contract.cdn_cluster_put_revenue( + ctx.contract.cluster_put_cdn_revenue( ctx.cluster_id, vec![(ctx.provider_id0, 1000), (ctx.provider_id0, 541643)], vec![(ctx.cdn_node_key0, 1000), (ctx.cdn_node_key1, 541643)], @@ -734,7 +734,8 @@ fn cdn_cluster_payment_works() { println!("Protocol revenues: {:?}", protocol_revenues); set_caller(ctx.provider_id0); - ctx.contract.cdn_cluster_distribute_revenues(ctx.cluster_id); + + ctx.contract.cluster_distribute_cdn_revenue(ctx.cluster_id); let cdn_node0 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key0).unwrap(); let cdn_node1 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key1).unwrap(); diff --git a/bucket/lib.rs b/bucket/lib.rs index 8ccd1ecb..e11c54ff 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -811,7 +811,7 @@ pub mod ddc_bucket { /// /// As a result CDN cluster revenue increases, which can be distributed between CDN node providers via method cdn_cluster_distribute_revenues. #[ink(message)] - pub fn cdn_cluster_put_revenue( + pub fn cluster_put_cdn_revenue( &mut self, cluster_id: ClusterId, aggregates_accounts: Vec<(AccountId, u128)>, @@ -819,7 +819,7 @@ pub mod ddc_bucket { aggregates_buckets: Vec<(BucketId, Resource)>, era: u64, ) -> () { - self.message_cdn_cluster_put_revenue( + self.message_cluster_put_cdn_revenue( cluster_id, aggregates_accounts, aggregates_nodes, @@ -835,8 +835,8 @@ pub mod ddc_bucket { /// /// Undistributed payments will be trasnferred, CDN cluster revenue will decrease. #[ink(message)] - pub fn cdn_cluster_distribute_revenues(&mut self, cluster_id: ClusterId) { - self.message_cdn_cluster_distribute_revenues(cluster_id) + pub fn cluster_distribute_cdn_revenue(&mut self, cluster_id: ClusterId) { + self.message_cluster_distribute_cdn_revenue(cluster_id) .unwrap() } From 49ca695c1201f2243063655d2ffad87874c51b55 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 28 Jun 2023 18:36:32 +0200 Subject: [PATCH 45/89] chore(test): test scenarious with err for adding storage node to a cluster --- bucket/ddc_bucket/cdn_node/entity.rs | 2 +- bucket/ddc_bucket/node/entity.rs | 4 +- bucket/ddc_bucket/tests/test_contract.rs | 342 ++++++++++++++++++----- bucket/lib.rs | 20 +- 4 files changed, 286 insertions(+), 82 deletions(-) diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index bca68fad..c6ce2a35 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -65,7 +65,7 @@ impl CdnNode { pub fn only_without_cluster(&self) -> Result<()> { self.cluster_id - .map_or(Ok(()), |cluster_id| Err(CdnNodeIsAlreadyAddedToCluster(cluster_id))) + .map_or(Ok(()), |cluster_id| Err(CdnNodeIsAddedToCluster(cluster_id))) } pub fn only_with_cluster(&self, cluster_id: ClusterId) -> Result<()> { diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index d8f8db09..29b2943b 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -90,12 +90,12 @@ impl Node { pub fn only_provider(&self, caller: AccountId) -> Result<()> { (self.provider_id == caller) .then(|| ()) - .ok_or(OnlyNodeOwner) + .ok_or(OnlyNodeProvider) } pub fn only_without_cluster(&self) -> Result<()> { self.cluster_id - .map_or(Ok(()), |cluster_id| Err(NodeIsAlreadyAddedToCluster(cluster_id))) + .map_or(Ok(()), |cluster_id| Err(NodeIsAddedToCluster(cluster_id))) } pub fn only_with_cluster(&self, cluster_id: ClusterId) -> Result<()> { diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs index 58e78b2e..1e759e43 100644 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ b/bucket/ddc_bucket/tests/test_contract.rs @@ -305,6 +305,7 @@ fn new_bucket(ctx: &mut TestCluster) -> TestBucket { } } + #[ink::test] fn cluster_create_works() { let ctx = new_cluster(); @@ -484,12 +485,275 @@ fn cluster_create_works() { } +#[ink::test] +fn cluster_node_add_err_if_node_in_cluster() { + let mut ctx = new_cluster(); + + let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + set_balance(another_manager_id, 1000 * TOKEN); + + set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); + let another_cluster_id = ctx.contract.cluster_create( + ClusterParams::from("{}") + )?; + + assert_eq!( + ctx.contract.cluster_add_node( + another_cluster_id, + ctx.node_key1, + ctx.v_nodes1, + ), + Err(NodeIsAddedToCluster(ctx.cluster_id)) + ); +} + + +#[ink::test] +fn cluster_node_add_err_if_not_trusted_manager() { + let mut ctx = new_cluster(); + + let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + set_balance(another_manager_id, 1000 * TOKEN); + + set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); + let another_cluster_id = ctx.contract.cluster_create( + ClusterParams::from("{}") + )?; + + let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + set_balance(new_provider_id, 1000 * TOKEN); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + let new_node_key = ctx.contract.node_create( + new_node_key, + NodeParams::from("new_node"), + 1000, + 100 + )?; + + let new_v_nodes: Vec = vec![10, 11, 12]; + set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); + assert_eq!( + ctx.contract.cluster_add_node( + another_cluster_id, + new_node_key, + new_v_nodes, + ), + Err(OnlyTrustedClusterManager) + ); +} + + +#[ink::test] +fn cluster_node_add_err_if_not_cluster_manager() { + let mut ctx = new_cluster(); + + let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + set_balance(another_manager_id, 1000 * TOKEN); + + set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); + let another_cluster_id = ctx.contract.cluster_create( + ClusterParams::from("{}") + )?; + + let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + set_balance(new_provider_id, 1000 * TOKEN); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + let new_node_key = ctx.contract.node_create( + new_node_key, + NodeParams::from("new_node"), + 1000, + 100 + )?; + + let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_manager_id, 1000 * TOKEN); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + ctx.contract.grant_trusted_manager_permission(not_manager_id)?; + + let new_v_nodes: Vec = vec![10, 11, 12]; + set_caller_value(not_manager_id, CONTRACT_FEE_LIMIT); + assert_eq!( + ctx.contract.cluster_add_node( + another_cluster_id, + new_node_key, + new_v_nodes, + ), + Err(OnlyClusterManager) + ); +} + + + +#[ink::test] +fn cluster_node_add_success() { + let mut ctx = new_cluster(); + + let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + set_balance(new_provider_id, 1000 * TOKEN); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_node_rent_per_month = 100; + let new_node_params = NodeParams::from("new_node"); + let new_node_capacity = 1000; + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + let new_node_key = ctx.contract.node_create( + new_node_key, + new_node_params.clone(), + new_node_capacity, + new_node_rent_per_month + )?; + + assert!( + matches!(get_events().pop().unwrap(), Event::NodeCreated(ev) if ev == + NodeCreated { + node_key: new_node_key, + provider_id: new_provider_id, + rent_per_month: new_node_rent_per_month, + node_params: new_node_params + }) + ); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + ctx.contract.grant_trusted_manager_permission(ctx.manager_id)?; + + assert!( + matches!( + get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == + PermissionGranted { + account_id: ctx.manager_id, + permission: Permission::ClusterManagerTrustedBy(new_provider_id) + } + ) + ); + + let new_v_nodes: Vec = vec![10, 11, 12]; + set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); + ctx.contract.cluster_add_node( + ctx.cluster_id, + new_node_key, + new_v_nodes.clone() + )?; + + assert!( + matches!(get_events().pop().unwrap(), Event::ClusterNodeAdded(ev) if ev == + ClusterNodeAdded { + cluster_id: ctx.cluster_id, + node_key: new_node_key + }) + ); + + let nodes_keys = vec![ + ctx.node_key0, + ctx.node_key1, + ctx.node_key2, + new_node_key, + ]; + + let cluster_v_nodes = vec![ + ctx.v_nodes0, + ctx.v_nodes1, + ctx.v_nodes2, + new_v_nodes + ]; + + let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; + cluster_info.cluster_v_nodes.sort(); + assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); + assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); +} + + +#[ink::test] +fn node_remove_err_if_not_provider() { + let mut ctx = new_cluster(); + + let not_provider = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_provider, 1000 * TOKEN); + + set_caller(not_provider); + assert_eq!( + ctx.contract.node_remove( + ctx.node_key1, + ), + Err(OnlyNodeProvider) + ); +} + + +#[ink::test] +fn node_remove_err_if_node_in_cluster() { + let mut ctx = new_cluster(); + + set_caller(ctx.provider_id1); + assert_eq!( + ctx.contract.node_remove( + ctx.node_key1, + ), + Err(NodeIsAddedToCluster(ctx.cluster_id)) + ); +} + + +#[ink::test] +fn cluster_node_remove_works() { + let mut ctx = new_cluster(); + + set_caller(ctx.manager_id); + ctx.contract.cluster_remove_node( + ctx.cluster_id, + ctx.node_key1 + )?; + + assert!( + matches!(get_events().pop().unwrap(), Event::ClusterNodeRemoved(ev) if ev == + ClusterNodeRemoved { + cluster_id: ctx.cluster_id, + node_key: ctx.node_key1 + }) + ); + + set_caller(ctx.provider_id1); + ctx.contract.node_remove(ctx.node_key1)?; + + assert!( + matches!(get_events().pop().unwrap(), Event::NodeRemoved(ev) if ev == + NodeRemoved { + node_key: ctx.node_key1 + }) + ); + + let nodes_keys = vec![ + ctx.node_key0, + ctx.node_key2, + ]; + + let cluster_v_nodes = vec![ + ctx.v_nodes0, + ctx.v_nodes2, + ]; + + let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; + cluster_info.cluster_v_nodes.sort(); + assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); + assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); + +} + + #[ink::test] fn cluster_replace_node_only_manager() { let mut ctx = new_cluster(); - let not_manager = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); - set_caller_value(not_manager, 0); + let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_caller_value(not_manager_id, 0); // Reassign a vnode from node1 to node2. assert_eq!( @@ -603,10 +867,10 @@ fn cluster_reserve_works() { fn cluster_management_validation_works() { let mut ctx = new_cluster(); - let not_manager = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); - set_balance(not_manager, 1000 * TOKEN); + let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_manager_id, 1000 * TOKEN); - set_caller(not_manager); + set_caller(not_manager_id); assert_eq!( ctx.contract.cluster_replace_node( ctx.cluster_id, @@ -853,66 +1117,6 @@ fn do_bucket_pays_cluster( Ok(()) } -#[ink::test] -fn cluster_add_node_works() { - let mut ctx = new_cluster(); - - let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); - set_balance(new_provider_id, 1000 * TOKEN); - - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); - let rent_per_month = 100; - let node_params = NodeParams::from("new_node"); - let capacity = 1000; - - set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - let new_node_key = ctx.contract.node_create( - new_node_key, - node_params.clone(), - capacity, - rent_per_month - )?; - - set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.grant_trusted_manager_permission(ctx.manager_id)?; - assert!( - matches!( - get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == - PermissionGranted { - account_id: ctx.manager_id, - permission: Permission::ClusterManagerTrustedBy(new_provider_id) - } - ) - ); - - let new_v_nodes = vec![10, 11, 12]; - set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); - ctx.contract.cluster_add_node( - ctx.cluster_id, - new_node_key, - new_v_nodes.clone() - )?; - - let nodes_keys = vec![ - ctx.node_key0, - ctx.node_key1, - ctx.node_key2, - new_node_key, - ]; - - let cluster_v_nodes = vec![ - ctx.v_nodes0, - ctx.v_nodes1, - ctx.v_nodes2, - new_v_nodes - ]; - - let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; - cluster_info.cluster_v_nodes.sort(); - assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); - assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); -} - #[ink::test] fn cluster_pays_providers() { @@ -1171,7 +1375,7 @@ fn node_set_params_only_owner() { ctx.node_key0, new_node_params ), - Err(OnlyNodeOwner) + Err(OnlyNodeProvider) ); } @@ -1193,11 +1397,11 @@ fn cluster_change_params_works() { fn cluster_change_params_only_owner() { let ctx = &mut new_cluster(); - let not_manager = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); - set_balance(not_manager, 1000 * TOKEN); + let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_manager_id, 1000 * TOKEN); // Change params. let new_cluster_params = NodeParams::from("new cluster params"); - set_caller_value(not_manager, CONTRACT_FEE_LIMIT); + set_caller_value(not_manager_id, CONTRACT_FEE_LIMIT); assert_eq!( ctx.contract.cluster_set_params( diff --git a/bucket/lib.rs b/bucket/lib.rs index e11c54ff..b1c2b32a 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -443,7 +443,7 @@ pub mod ddc_bucket { /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `OnlyTrustedClusterManager` error if the caller is not a trusted cluster manager. /// * `NodeDoesNotExist` error if the adding Storage node does not exist. - /// * `NodeIsAlreadyAddedToCluster(ClusterId)` error if the adding Storage node is already added to this or another cluster. + /// * `NodeIsAddedToCluster(ClusterId)` error if the adding Storage node is already added to this or another cluster. #[ink(message, payable)] pub fn cluster_add_node( &mut self, @@ -513,7 +513,7 @@ pub mod ddc_bucket { /// * `OnlyClusterManager` error if the caller is not the cluster manager. /// * `NodeDoesNotExist` error if the new Storage node does not exist. /// * `NodeIsNotAddedToCluster(ClusterId)` error if the new Storage node is not added to this cluster. - /// * `NodeIsAlreadyAddedToCluster(ClusterId)` error if the new Storage node is in another cluster. + /// * `NodeIsAddedToCluster(ClusterId)` error if the new Storage node is in another cluster. /// * `VNodeInNotAssignedToNode(ClusterId, VNodeToken)` error if the there is some virtual node that is being reasigned, but this virtual node is not assigned to any physical node. /// * `VNodeIsAlreadyAssignedToNode(NodeKey)` - error if there is some virtual node that is already assigned to other physical node within the same cluster. #[ink(message)] @@ -553,7 +553,7 @@ pub mod ddc_bucket { /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `OnlyTrustedClusterManager` error if the caller is not a trusted cluster manager. /// * `CdnNodeDoesNotExist` error if the adding CDN node does not exist. - /// * `CdnNodeIsAlreadyAddedToCluster(ClusterId)` error if the adding CDN node is already added to this or another cluster. + /// * `CdnNodeIsAddedToCluster(ClusterId)` error if the adding CDN node is already added to this or another cluster. #[ink(message, payable)] pub fn cluster_add_cdn_node( &mut self, @@ -991,7 +991,7 @@ pub mod ddc_bucket { /// /// * `OnlyCdnNodeOwner` error if the caller is not the CDN node owner. /// * `CdnNodeDoesNotExist` error if the CDN node does not exist. - /// * `CdnNodeIsAlreadyAddedToCluster(ClusterId)` error if the removing CDN node is added to some cluster. + /// * `CdnNodeIsAddedToCluster(ClusterId)` error if the removing CDN node is added to some cluster. #[ink(message)] pub fn cdn_node_remove( &mut self, @@ -1172,9 +1172,9 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `OnlyNodeOwner` error if the caller is not the Storage node owner. + /// * `OnlyNodeProvider` error if the caller is not the Storage node owner. /// * `NodeDoesNotExist` error if the Storage node does not exist. - /// * `NodeIsAlreadyAddedToCluster(ClusterId)` error if the removing Storage node is added to some cluster. + /// * `NodeIsAddedToCluster(ClusterId)` error if the removing Storage node is added to some cluster. #[ink(message)] pub fn node_remove( &mut self, @@ -1203,7 +1203,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `OnlyNodeOwner` error if the caller is not the Storage node owner. + /// * `OnlyNodeProvider` error if the caller is not the Storage node owner. /// * `NodeDoesNotExist` error if the Storage node does not exist. #[ink(message, payable)] pub fn node_set_params( @@ -1668,7 +1668,7 @@ pub mod ddc_bucket { ParamsDoesNotExist, ParamsSizeExceedsLimit, OnlyOwner, - OnlyNodeOwner, + OnlyNodeProvider, OnlyCdnNodeOwner, OnlyClusterManager, OnlyTrustedClusterManager, @@ -1681,9 +1681,9 @@ pub mod ddc_bucket { TopologyIsNotCreated(ClusterId), TopologyAlreadyExists, NodeIsNotAddedToCluster(ClusterId), - NodeIsAlreadyAddedToCluster(ClusterId), + NodeIsAddedToCluster(ClusterId), CdnNodeIsNotAddedToCluster(ClusterId), - CdnNodeIsAlreadyAddedToCluster(ClusterId), + CdnNodeIsAddedToCluster(ClusterId), VNodeDoesNotExistsInCluster(ClusterId), VNodeInNotAssignedToNode(ClusterId, VNodeToken), VNodeIsAlreadyAssignedToNode(NodeKey), From 767bf717790b9fde7ea969c62ad3e387680324a2 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 28 Jun 2023 19:47:41 +0200 Subject: [PATCH 46/89] chore(test): tests are splited to modules --- bucket/ddc_bucket/tests/env_utils.rs | 1 + bucket/ddc_bucket/tests/mod.rs | 7 +- bucket/ddc_bucket/tests/setup_utils.rs | 297 ++++ bucket/ddc_bucket/tests/test_account.rs | 75 + bucket/ddc_bucket/tests/test_admin.rs | 42 +- bucket/ddc_bucket/tests/test_bucket.rs | 270 ++++ bucket/ddc_bucket/tests/test_cluster.rs | 781 +++++++++++ bucket/ddc_bucket/tests/test_contract.rs | 1592 ---------------------- bucket/ddc_bucket/tests/test_currency.rs | 53 +- bucket/ddc_bucket/tests/test_node.rs | 149 ++ 10 files changed, 1637 insertions(+), 1630 deletions(-) create mode 100644 bucket/ddc_bucket/tests/setup_utils.rs create mode 100644 bucket/ddc_bucket/tests/test_account.rs create mode 100644 bucket/ddc_bucket/tests/test_bucket.rs create mode 100644 bucket/ddc_bucket/tests/test_cluster.rs delete mode 100644 bucket/ddc_bucket/tests/test_contract.rs create mode 100644 bucket/ddc_bucket/tests/test_node.rs diff --git a/bucket/ddc_bucket/tests/env_utils.rs b/bucket/ddc_bucket/tests/env_utils.rs index 64f6d2db..b25ae51e 100644 --- a/bucket/ddc_bucket/tests/env_utils.rs +++ b/bucket/ddc_bucket/tests/env_utils.rs @@ -12,6 +12,7 @@ use crate::ddc_bucket::*; pub type Event = ::Type; +pub const KB_PER_GB: Balance = 1_000_000; /// Recommended contract fee for all operations with reasonable data amounts. pub const CONTRACT_FEE_LIMIT: Balance = 10 * TOKEN; diff --git a/bucket/ddc_bucket/tests/mod.rs b/bucket/ddc_bucket/tests/mod.rs index c82a3596..5bf0930d 100644 --- a/bucket/ddc_bucket/tests/mod.rs +++ b/bucket/ddc_bucket/tests/mod.rs @@ -1,6 +1,9 @@ mod env_utils; +mod setup_utils; mod test_admin; -mod test_contract; mod test_currency; -// mod test_committer; +mod test_node; +mod test_cluster; +mod test_bucket; +mod test_account; diff --git a/bucket/ddc_bucket/tests/setup_utils.rs b/bucket/ddc_bucket/tests/setup_utils.rs new file mode 100644 index 00000000..b971d7d8 --- /dev/null +++ b/bucket/ddc_bucket/tests/setup_utils.rs @@ -0,0 +1,297 @@ + +use crate::ddc_bucket::*; +use super::env_utils::*; + + +pub fn setup_contract() -> DdcBucket { + set_caller(admin_id()); + set_callee(contract_id()); + let contract = DdcBucket::new(); + set_balance(contract_id(), 10); + contract +} + + +pub struct TestCluster { + pub contract: DdcBucket, + + pub provider_id0: AccountId, + pub provider_id1: AccountId, + pub provider_id2: AccountId, + + pub node_key0: NodeKey, + pub node_key1: NodeKey, + pub node_key2: NodeKey, + pub node_params0: NodeParams, + pub node_params1: NodeParams, + pub node_params2: NodeParams, + pub v_nodes0: Vec, + pub v_nodes1: Vec, + pub v_nodes2: Vec, + + pub cdn_node_key0: CdnNodeKey, + pub cdn_node_key1: CdnNodeKey, + pub cdn_node_key2: CdnNodeKey, + pub cdn_node_params0: CdnNodeParams, + pub cdn_node_params1: CdnNodeParams, + pub cdn_node_params2: CdnNodeParams, + + pub manager_id: AccountId, + pub cluster_id: ClusterId, + pub cluster_params: ClusterParams, + pub cluster_v_nodes: Vec, + pub nodes_keys: Vec, + pub cdn_nodes_keys: Vec, + pub rent_per_v_node: Balance, + pub capacity: u32, + pub reserved_resource: u32, +} + +pub fn setup_cluster() -> TestCluster { + + let mut contract: DdcBucket = setup_contract(); + + let provider_id0 = AccountId::from([0xae, 0x7d, 0xe8, 0x17, 0xa4, 0xa5, 0x12, 0x57, 0xd2, 0x49, 0x64, 0x28, 0x3b, 0x25, 0x69, 0x09, 0xdf, 0x0c, 0x99, 0x97, 0xc0, 0x3e, 0x2b, 0x88, 0x02, 0x02, 0xee, 0x10, 0xf4, 0x4d, 0x72, 0x48]); + let provider_id1 = AccountId::from([0xc4, 0xba, 0xfd, 0x6a, 0xa1, 0x5a, 0x14, 0xd6, 0xee, 0xf2, 0xea, 0x92, 0xb7, 0xc6, 0x84, 0x51, 0x68, 0x39, 0xbe, 0x96, 0xd6, 0xbf, 0xca, 0xa3, 0x68, 0xd2, 0x4f, 0xff, 0x09, 0x85, 0xa7, 0x1e]); + let provider_id2 = AccountId::from([0xfa, 0x01, 0x28, 0xf8, 0xe1, 0x32, 0xc6, 0x81, 0x21, 0x06, 0xa5, 0xce, 0xae, 0x6d, 0xcf, 0xf3, 0xd2, 0xc0, 0x1b, 0xb0, 0x13, 0xf2, 0xd7, 0x75, 0x6f, 0x20, 0xf9, 0x50, 0x00, 0xd6, 0xc7, 0x2b]); + let manager_id = AccountId::from([0xd2, 0xc5, 0xea, 0xa2, 0x0c, 0xd0, 0x4e, 0xfb, 0x3f, 0x10, 0xb8, 0xad, 0xa9, 0xa4, 0x4f, 0xe0, 0x85, 0x41, 0x1f, 0x59, 0xf2, 0x34, 0x1a, 0x92, 0xa3, 0x48, 0x4f, 0x04, 0x51, 0x87, 0x68, 0x54]); + + set_balance(provider_id0, 1000 * TOKEN); + set_balance(provider_id1, 1000 * TOKEN); + set_balance(provider_id2, 1000 * TOKEN); + set_balance(manager_id, 1000 * TOKEN); + + let rent_per_v_node: Balance = 10 * TOKEN; + let reserved_resource = 10; + let capacity = 100; + + + // Create the 1st storage node + let node_key0 = AccountId::from([0x0a; 32]); + let node_params0 = NodeParams::from("{\"url\":\"https://ddc.cere.network/storage/0\"}"); + let capacity0 = capacity; + set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); + contract.node_create( + node_key0, + node_params0.clone(), + capacity0, + rent_per_v_node + ).unwrap(); + + + // Create the 2nd storage node + let node_key1 = AccountId::from([0x0b; 32]); + let node_params1 = NodeParams::from("{\"url\":\"https://ddc-1.cere.network/storage/1\"}"); + let capacity1 = capacity; + set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); + contract.node_create( + node_key1, + node_params1.clone(), + capacity1, + rent_per_v_node + ).unwrap(); + + + // Create the 3rd storage node + let node_key2 = AccountId::from([0x0c; 32]); + let node_params2 = NodeParams::from("{\"url\":\"https://ddc-2.cere.network/storage/2\"}"); + let capacity2 = capacity; + set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); + let node_key2 = contract.node_create( + node_key2, + node_params2.clone(), + capacity2, + rent_per_v_node, + ).unwrap(); + + + // Create the 1st cdn node + let cdn_node_key0 = AccountId::from([0x0d; 32]); + let cdn_node_params0 = CdnNodeParams::from("{\"url\":\"https://ddc.cere.network/cdn/0\"}"); + set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); + contract.cdn_node_create( + cdn_node_key0, + cdn_node_params0.clone() + ).unwrap(); + + + // Create the 2nd cdn node + let cdn_node_key1 = AccountId::from([0x0e; 32]); + let cdn_node_params1 = CdnNodeParams::from("{\"url\":\"https://ddc.cere.network/cdn/1\"}"); + set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); + contract.cdn_node_create( + cdn_node_key1, + cdn_node_params1.clone() + ).unwrap(); + + + // Create the 3rd cdn node + let cdn_node_key2 = AccountId::from([0x0f; 32]); + let cdn_node_params2 = CdnNodeParams::from("{\"url\":\"https://ddc.cere.network/cdn/2\"}"); + set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); + contract.cdn_node_create( + cdn_node_key2, + cdn_node_params2.clone() + ).unwrap(); + + + // Create a Cluster + let cluster_params = ClusterParams::from("{}"); + set_caller_value(manager_id, CONTRACT_FEE_LIMIT); + let cluster_id = contract.cluster_create( + cluster_params.clone(), + ).unwrap(); + + + // Grant trusted manager_id permission from node providers to the cluster manager_id + for provider_id in [provider_id0, provider_id1, provider_id2] { + set_caller_value(provider_id, CONTRACT_FEE_LIMIT); + contract.grant_trusted_manager_permission(manager_id).unwrap(); + let expected_perm = Permission::ClusterManagerTrustedBy(provider_id); + assert!(contract.has_permission(manager_id, expected_perm)); + } + + + // Add the 1st storage node to the Cluster + let v_nodes0 = vec![1, 2, 3]; + set_caller_value(manager_id, CONTRACT_FEE_LIMIT); + contract.cluster_add_node( + cluster_id, + node_key0, + v_nodes0.clone() + ).unwrap(); + + + // Add the 2nd storage node to the Cluster + let v_nodes1 = vec![4, 5, 6]; + set_caller_value(manager_id, CONTRACT_FEE_LIMIT); + contract.cluster_add_node( + cluster_id, + node_key1, + v_nodes1.clone() + ).unwrap(); + + + // Add the 3rd storage node to the Cluster + let v_nodes2 = vec![7, 8, 9]; + set_caller_value(manager_id, CONTRACT_FEE_LIMIT); + contract.cluster_add_node( + cluster_id, + node_key2, + v_nodes2.clone() + ).unwrap(); + + + // Add the 1st cdn node to the Cluster + set_caller_value(manager_id, CONTRACT_FEE_LIMIT); + contract.cluster_add_cdn_node( + cluster_id, + cdn_node_key0, + ).unwrap(); + + + // Add the 2nd cdn node to the Cluster + set_caller_value(manager_id, CONTRACT_FEE_LIMIT); + contract.cluster_add_cdn_node( + cluster_id, + cdn_node_key1, + ).unwrap(); + + + // Add the 3rd cdn node to the Cluster + set_caller_value(manager_id, CONTRACT_FEE_LIMIT); + contract.cluster_add_cdn_node( + cluster_id, + cdn_node_key2, + ).unwrap(); + + + set_caller(manager_id); + contract.cluster_reserve_resource(cluster_id, reserved_resource); + + + let nodes_keys = vec![ + node_key0, + node_key1, + node_key2 + ]; + + let cdn_nodes_keys = vec![ + cdn_node_key0, + cdn_node_key1, + cdn_node_key2 + ]; + + let mut cluster_v_nodes = Vec::::new(); + cluster_v_nodes.extend(v_nodes0.clone()); + cluster_v_nodes.extend(v_nodes1.clone()); + cluster_v_nodes.extend(v_nodes2.clone()); + + TestCluster { + contract, + + provider_id0, + provider_id1, + provider_id2, + + node_key0, + node_key1, + node_key2, + node_params0, + node_params1, + node_params2, + v_nodes0, + v_nodes1, + v_nodes2, + + cdn_node_key0, + cdn_node_key1, + cdn_node_key2, + cdn_node_params0, + cdn_node_params1, + cdn_node_params2, + + manager_id, + cluster_id, + cluster_params, + cluster_v_nodes, + rent_per_v_node, + nodes_keys, + cdn_nodes_keys, + capacity, + reserved_resource, + } +} + +pub struct TestBucket { + pub bucket_id: BucketId, + pub owner_id: AccountId, + pub resource: u32, +} + +pub fn setup_bucket(ctx: &mut TestCluster) -> TestBucket { + let owner_id = AccountId::from([0xd4, 0x8f, 0x63, 0x67, 0xe2, 0x15, 0x51, 0xdf, 0x11, 0x1c, 0x92, 0x69, 0x0d, 0x04, 0x3f, 0x75, 0xcb, 0x39, 0xf8, 0x27, 0xbb, 0xc7, 0x46, 0x4b, 0x8d, 0x5d, 0x70, 0xd1, 0x02, 0xaa, 0x71, 0x0a]); + set_balance(owner_id, 1000 * TOKEN); + set_caller_value(owner_id, CONTRACT_FEE_LIMIT); + + let bucket_id = ctx.contract.bucket_create( + "{}".to_string(), + ctx.cluster_id, + None + ); + + // Reserve some resources for the bucket from the cluster. + set_caller_value(owner_id, CONTRACT_FEE_LIMIT); + let resource = 1; + ctx.contract.bucket_alloc_into_cluster(bucket_id, resource); + + // Deposit some value to pay for buckets. + set_caller_value(owner_id, 10 * TOKEN); + ctx.contract.account_deposit(); + + TestBucket { + bucket_id, + owner_id, + resource, + } +} \ No newline at end of file diff --git a/bucket/ddc_bucket/tests/test_account.rs b/bucket/ddc_bucket/tests/test_account.rs new file mode 100644 index 00000000..76aae63b --- /dev/null +++ b/bucket/ddc_bucket/tests/test_account.rs @@ -0,0 +1,75 @@ +use ink_lang as ink; + +use crate::ddc_bucket::*; +use crate::ddc_bucket::Error::*; +use super::env_utils::*; +use super::setup_utils::*; +use crate::ddc_bucket::schedule::{Schedule}; + + +#[ink::test] +fn account_deposit_success() { + let account_id = AccountId::from([0x76, 0x95, 0x7c, 0xa6, 0xbe, 0xf5, 0xa3, 0x6d, 0x67, 0x0d, 0x3a, 0x84, 0xc6, 0x0a, 0xe2, 0xbb, 0xc9, 0x5e, 0xee, 0xde, 0x3a, 0x5f, 0x27, 0x0e, 0x26, 0xe3, 0x43, 0x4c, 0x46, 0xe2, 0x98, 0x10]); + set_balance(account_id, 1000 * TOKEN); + + let mut contract = setup_contract(); + + assert_eq!( + contract.account_get(account_id), + Err(AccountDoesNotExist), + "must not get a non-existent account" + ); + + let deposit = 10 * TOKEN; + let deposit_after_fee = deposit; + + // Deposit some value. + set_caller_value(account_id, deposit); + contract.account_deposit(); + + let account = contract.account_get(account_id)?; + assert_eq!( + account, + Account { + deposit: Cash(deposit_after_fee), + payable_schedule: Schedule::empty(), + bonded: Cash(0), + unbonded_amount: Cash(0), + negative: Cash(0), + unbonded_timestamp: 0, + }, + "must take deposit minus creation fee" + ); + + // Deposit more value. + set_caller_value(account_id, deposit); + contract.account_deposit(); + + let account = contract.account_get(account_id)?; + assert_eq!( + account, + Account { + deposit: Cash(deposit_after_fee + deposit), + payable_schedule: Schedule::empty(), + bonded: Cash(0), + unbonded_amount: Cash(0), + negative: Cash(0), + unbonded_timestamp: 0, + }, + "must take more deposits without creation fee" + ); + + // Check events. + let mut events = get_events(); + events.reverse(); // Work with pop(). + + // First deposit event. + assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == + Deposit { account_id, value: deposit_after_fee })); + + // Second deposit event. No deposit_contract_fee because the account already exists. + assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == + Deposit { account_id, value: deposit })); + + assert_eq!(events.len(), 0, "all events must be checked"); +} diff --git a/bucket/ddc_bucket/tests/test_admin.rs b/bucket/ddc_bucket/tests/test_admin.rs index 87e25acb..e3f2e28b 100644 --- a/bucket/ddc_bucket/tests/test_admin.rs +++ b/bucket/ddc_bucket/tests/test_admin.rs @@ -2,12 +2,17 @@ use ink_lang as ink; use crate::ddc_bucket::*; use crate::ddc_bucket::Error::*; - use super::env_utils::*; +use super::setup_utils::*; + + +fn not_admin_id() -> AccountId { + get_accounts().bob +} #[ink::test] fn admin_init_works() { - let contract = setup(); + let contract = setup_contract(); // The deployer is SuperAdmin. assert!(contract.has_permission(admin_id(), Permission::SuperAdmin)); @@ -18,9 +23,10 @@ fn admin_init_works() { assert!(!contract.has_permission(not_admin_id(), Permission::SetExchangeRate)); } + #[ink::test] fn admin_withdraw_works() { - let mut contract = setup(); + let mut contract = setup_contract(); assert_eq!(balance_of(contract_id()), 10); set_caller(admin_id()); @@ -33,23 +39,24 @@ fn admin_withdraw_works() { #[ink::test] #[should_panic] fn admin_withdraw_only_admin() { - let mut contract = setup(); + let mut contract = setup_contract(); set_caller(not_admin_id()); contract.admin_withdraw(9); // panic. } + #[ink::test] fn admin_grant_works() { - let mut contract = setup(); + let mut contract = setup_contract(); let permission = Permission::SuperAdmin; set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); let new_admin_id = not_admin_id(); - contract.admin_grant_permission(new_admin_id, permission); + contract.admin_grant_permission(new_admin_id, permission)?; // Check the last event. let ev = get_events().pop().unwrap(); @@ -63,9 +70,10 @@ fn admin_grant_works() { contract.admin_withdraw(9); } + #[ink::test] fn admin_grant_only_admin() { - let mut contract = setup(); + let mut contract = setup_contract(); set_caller_value(not_admin_id(), CONTRACT_FEE_LIMIT); @@ -78,15 +86,16 @@ fn admin_grant_only_admin() { ); } + #[ink::test] #[should_panic] fn admin_revoke_works() { - let mut contract = setup(); + let mut contract = setup_contract(); let permission = Permission::SuperAdmin; set_caller(admin_id()); - contract.admin_revoke_permission(admin_id(), permission); + contract.admin_revoke_permission(admin_id(), permission)?; // Check the last event. let ev = get_events().pop().unwrap(); @@ -101,9 +110,10 @@ fn admin_revoke_works() { contract.admin_withdraw(9); // panic. } + #[ink::test] fn admin_revoke_only_admin() { - let mut contract = setup(); + let mut contract = setup_contract(); set_caller_value(not_admin_id(), CONTRACT_FEE_LIMIT); @@ -114,16 +124,4 @@ fn admin_revoke_only_admin() { ), Err(OnlySuperAdmin) ); -} - -fn setup() -> DdcBucket { - set_caller(admin_id()); - set_callee(contract_id()); - let contract = DdcBucket::new(); - set_balance(contract_id(), 10); - contract -} - -fn not_admin_id() -> AccountId { - get_accounts().bob } \ No newline at end of file diff --git a/bucket/ddc_bucket/tests/test_bucket.rs b/bucket/ddc_bucket/tests/test_bucket.rs new file mode 100644 index 00000000..8c65fde8 --- /dev/null +++ b/bucket/ddc_bucket/tests/test_bucket.rs @@ -0,0 +1,270 @@ +use ink_lang as ink; + +use crate::ddc_bucket::*; +use crate::ddc_bucket::flow::Flow; +use crate::ddc_bucket::schedule::{Schedule, MS_PER_MONTH}; +use super::env_utils::*; +use super::setup_utils::*; + + +fn do_bucket_pays_cluster( + ctx: &mut TestCluster, + test_bucket: &TestBucket, + usd_per_cere: Balance, +) -> Result<()> { + let expected_rent = ctx.rent_per_v_node * ctx.cluster_v_nodes.len() as Balance; + + // Check the state before payment. + let before = ctx + .contract + .account_get(test_bucket.owner_id)? + .deposit + .peek(); + let bucket = ctx.contract.bucket_get(test_bucket.bucket_id)?.bucket; + assert_eq!(bucket.owner_id, test_bucket.owner_id); + /* TODO: Not testable at the moment, see struct BucketInStatus. + assert_eq!(bucket.flow, + Flow { + from: test_bucket.owner_id, + schedule: Schedule::new(0, expected_rent), + }); + */ + let timestamp_before = block_timestamp::(); + // Go to the future when some revenues are due. + advance_block::(); + // Pay the due thus far. + set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); + ctx.contract.bucket_settle_payment(test_bucket.bucket_id); + let timestamp_after = block_timestamp::(); + + // Check the last event. + let ev = get_events().pop().unwrap(); + assert!(matches!(ev, Event::BucketSettlePayment(ev) if ev == + BucketSettlePayment { + bucket_id: test_bucket.bucket_id, + cluster_id: ctx.cluster_id + } + )); + + // Check the state after payment. + let after = ctx + .contract + .account_get(test_bucket.owner_id)? + .deposit + .peek(); + let spent = before - after; + /* TODO: Not testable at the moment, see struct BucketInStatus. + let bucket = ctx.contract.bucket_get(test_bucket.bucket_id)?.bucket; + assert_eq!(bucket.flow, + Flow { + from: test_bucket.owner_id, + schedule: Schedule::new(BLOCK_TIME, expected_rent), + }); + */ + let timespan = timestamp_after - timestamp_before; + let expect_revenues_usd = expected_rent * timespan as u128 / MS_PER_MONTH as u128; + let expect_revenues = expect_revenues_usd / usd_per_cere; + assert!(expect_revenues > 0); + assert_eq!( + expect_revenues, spent, + "revenues must come from the bucket owner" + ); + + let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; + assert_eq!( + cluster.revenues.peek(), + expect_revenues, + "must get revenues into the cluster" + ); + + Ok(()) +} + + +#[ink::test] +fn bucket_pays_cluster_success() { + let ctx = &mut setup_cluster(); + let test_bucket = &setup_bucket(ctx); + do_bucket_pays_cluster(ctx, test_bucket, 1).unwrap(); +} + + +#[ink::test] +fn bucket_pays_cluster_at_new_rate_success() { + let ctx = &mut setup_cluster(); + + let test_bucket = &setup_bucket(ctx); + // Set up an exchange rate manager_id. + set_caller(admin_id()); + ctx.contract + .admin_grant_permission(admin_id(), Permission::SetExchangeRate).unwrap(); + + + // Change the currency exchange rate. + let usd_per_cere = 2; + set_caller(admin_id()); + ctx.contract.account_set_usd_per_cere(usd_per_cere * TOKEN); + + do_bucket_pays_cluster(ctx, test_bucket, usd_per_cere).unwrap(); +} + + +#[ink::test] +fn bucket_create_success() { + let ctx = &mut setup_cluster(); + let test_bucket = &setup_bucket(ctx); + + // Check the structure of the bucket including the payment flow. + let total_rent = ctx.rent_per_v_node * ctx.cluster_v_nodes.len() as Balance; + let expect_bucket = Bucket { + owner_id: test_bucket.owner_id, + cluster_id: ctx.cluster_id, + flow: Flow { + from: test_bucket.owner_id, + schedule: Schedule::new(0, total_rent), + }, + resource_reserved: test_bucket.resource, + public_availability: false, + resource_consumption_cap: 0, + }; + + // Check the status of the bucket. + let bucket_status = ctx.contract.bucket_get(test_bucket.bucket_id)?; + assert_eq!( + bucket_status, + BucketStatus { + bucket_id: test_bucket.bucket_id, + bucket: expect_bucket.into(), + params: "{}".to_string(), + writer_ids: vec![test_bucket.owner_id], + reader_ids: vec![], + rent_covered_until_ms: 297600000, // TODO: check this value. + } + ); + + let mut events = get_events(); + events.reverse(); // Work with pop(). + events.truncate(8 - 3 - 2); // Skip 3 NodeCreated and 2 cluster setup_contract events. + + // Create bucket. + assert!( + matches!(events.pop().unwrap(), Event::BucketCreated(ev) if ev == + BucketCreated { bucket_id: test_bucket.bucket_id, owner_id: test_bucket.owner_id }) + ); + + assert!( + matches!(events.pop().unwrap(), Event::BucketAllocated(ev) if ev == + BucketAllocated { bucket_id: test_bucket.bucket_id, cluster_id: ctx.cluster_id, resource: test_bucket.resource }) + ); + + // Deposit more. + let net_deposit = 10 * TOKEN; + assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == + Deposit { account_id: test_bucket.owner_id, value: net_deposit })); + + assert_eq!(events.len(), 0, "all events must be checked"); +} + + +#[ink::test] +fn bucket_change_params_success() { + let ctx = &mut setup_cluster(); + let test_bucket = &setup_bucket(ctx); + + // Change params. + set_caller_value(test_bucket.owner_id, CONTRACT_FEE_LIMIT); + ctx.contract + .bucket_change_params(test_bucket.bucket_id, "new params".to_string()); + + // Check the changed params. + let status = ctx.contract.bucket_get(test_bucket.bucket_id)?; + assert_eq!(status.params, "new params"); +} + +#[ink::test] +#[should_panic] +fn bucket_change_params_only_owner() { + let ctx = &mut setup_cluster(); + let test_bucket = &setup_bucket(ctx); + + // Change params. + set_caller_value(get_accounts().bob, CONTRACT_FEE_LIMIT); + ctx.contract + .bucket_change_params(test_bucket.bucket_id, "new params".to_string()); + // Panic. +} + + +#[ink::test] +fn bucket_list_success() { + let mut ddc_bucket = setup_contract(); + + let owner_id1 = AccountId::from([0xd8, 0x69, 0x19, 0x54, 0xea, 0xdc, 0x9a, 0xc0, 0x3d, 0x37, 0x56, 0x9f, 0x2a, 0xe8, 0xdf, 0x59, 0x34, 0x3f, 0x32, 0x65, 0xba, 0xd4, 0x16, 0xac, 0x07, 0xdf, 0x06, 0xeb, 0x4d, 0xbc, 0x6a, 0x66]); + set_balance(owner_id1, 1000 * TOKEN); + let owner_id2 = AccountId::from([0x2a, 0x5f, 0xbc, 0xcf, 0x71, 0x0b, 0x65, 0x04, 0x88, 0x91, 0x12, 0x7e, 0x5e, 0xe3, 0x78, 0xdb, 0x48, 0x63, 0x09, 0x44, 0xcc, 0xc5, 0x75, 0xbd, 0xa5, 0xaa, 0xa5, 0x0e, 0x77, 0xab, 0x7b, 0x4e]); + set_balance(owner_id2, 1000 * TOKEN); + let owner_id3 = AccountId::from([0x64, 0xef, 0xd7, 0xb4, 0x41, 0xb2, 0x58, 0xb5, 0x56, 0x6b, 0xfc, 0x4b, 0x19, 0xb8, 0xe5, 0x09, 0x5d, 0x17, 0xb3, 0xc3, 0x44, 0x38, 0x58, 0xa9, 0x7d, 0x20, 0x49, 0x39, 0xbd, 0xbd, 0xb6, 0x48]); + set_balance(owner_id3, 1000 * TOKEN); + + let cluster_id = 0; + + set_caller_value(owner_id1, CONTRACT_FEE_LIMIT); + let bucket_id1 = ddc_bucket.bucket_create("".to_string(), cluster_id, None); + let bucket_status1 = ddc_bucket.bucket_get(bucket_id1).unwrap(); + + set_caller_value(owner_id2, CONTRACT_FEE_LIMIT); + let bucket_id2 = ddc_bucket.bucket_create("".to_string(), cluster_id, None); + let bucket_status2 = ddc_bucket.bucket_get(bucket_id2)?; + + assert_ne!(bucket_id1, bucket_id2); + let count = 2; + + assert_eq!( + ddc_bucket.bucket_list(0, 100, None), + (vec![bucket_status1.clone(), bucket_status2.clone()], count) + ); + + assert_eq!( + ddc_bucket.bucket_list(0, 2, None), + (vec![bucket_status1.clone(), bucket_status2.clone()], count) + ); + + assert_eq!( + ddc_bucket.bucket_list(0, 1, None), + ( + vec![bucket_status1.clone()], + count + ) + ); + assert_eq!( + ddc_bucket.bucket_list(1, 1, None), + ( + vec![bucket_status2.clone()], + count + ) + ); + + assert_eq!(ddc_bucket.bucket_list(count, 20, None), (vec![], count)); + + // Filter by owner. + assert_eq!( + ddc_bucket.bucket_list(0, 100, Some(owner_id1)), + ( + vec![bucket_status1.clone()], + count + ) + ); + + assert_eq!( + ddc_bucket.bucket_list(0, 100, Some(owner_id2)), + ( + vec![bucket_status2.clone()], + count + ) + ); + + assert_eq!( + ddc_bucket.bucket_list(0, 100, Some(owner_id3)), + (vec![], count) + ); +} diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs new file mode 100644 index 00000000..62e95188 --- /dev/null +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -0,0 +1,781 @@ +use ink_lang as ink; + +use crate::ddc_bucket::Error::*; +use crate::ddc_bucket::*; +use super::env_utils::*; +use super::setup_utils::*; + + +#[ink::test] +fn cluster_create_success() { + let ctx = setup_cluster(); + let providers_ids = &[ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; + let node_keys = &[ctx.node_key0, ctx.node_key1, ctx.node_key2]; + let cdn_node_keys = &[ctx.cdn_node_key0, ctx.cdn_node_key1, ctx.cdn_node_key2]; + let node_params = &[ctx.node_params0.clone(), ctx.node_params1.clone(), ctx.node_params2.clone()]; + let cdn_node_params = &[ctx.cdn_node_params0.clone(), ctx.cdn_node_params1.clone(), ctx.cdn_node_params2.clone()]; + + assert_eq!(ctx.cluster_id, 0, "cluster_id must start at 0"); + + // Check cluster nodes + { + let node0 = ctx.contract.node_get(ctx.node_key0)?; + let v_nodes0 = ctx.contract.get_v_nodes_by_node(ctx.node_key0); + + assert_eq!( + node0, + NodeInfo { + node_key: ctx.node_key0, + node: Node { + provider_id: ctx.provider_id0, + rent_per_month: ctx.rent_per_v_node, + free_resource: ctx.capacity - ctx.reserved_resource * 3, + node_params: ctx.node_params0.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + v_nodes: v_nodes0 + } + ); + + let node1 = ctx.contract.node_get(ctx.node_key1)?; + let v_nodes1 = ctx.contract.get_v_nodes_by_node(ctx.node_key1); + + assert_eq!( + node1, + NodeInfo { + node_key: ctx.node_key1, + node: Node { + provider_id: ctx.provider_id1, + rent_per_month: ctx.rent_per_v_node, + free_resource: ctx.capacity - ctx.reserved_resource * 3, + node_params: ctx.node_params1.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + v_nodes: v_nodes1 + } + ); + + let node2 = ctx.contract.node_get(ctx.node_key2)?; + let v_nodes2 = ctx.contract.get_v_nodes_by_node(ctx.node_key2); + + assert_eq!( + node2, + NodeInfo { + node_key: ctx.node_key2, + node: Node { + provider_id: ctx.provider_id2, + rent_per_month: ctx.rent_per_v_node, + free_resource: ctx.capacity - ctx.reserved_resource * 3, + node_params: ctx.node_params2.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + v_nodes: v_nodes2 + } + ); + } + + // Check the cluster + { + let cluster = ctx.contract.cluster_get(ctx.cluster_id)?; + let cluster_v_nodes = ctx.contract.get_v_nodes_by_cluster(ctx.cluster_id); + assert_eq!( + cluster, + ClusterInfo { + cluster_id: ctx.cluster_id, + cluster: Cluster { + manager_id: ctx.manager_id, + nodes_keys: ctx.nodes_keys, + resource_per_v_node: ctx.reserved_resource, + resource_used: 0, + cluster_params: ctx.cluster_params.clone(), + revenues: Cash(0), + total_rent: ctx.rent_per_v_node * ctx.cluster_v_nodes.len() as Balance, + cdn_nodes_keys: ctx.cdn_nodes_keys, + cdn_usd_per_gb: 104_857_600, + cdn_revenues: Cash(0), + }, + cluster_v_nodes + } + ); + } + + // Check emitted events + let mut events = get_events(); + events.reverse(); // Work with pop(). + + // Storage node created event + for i in 0..3 { + assert!(matches!(events.pop().unwrap(), Event::NodeCreated(ev) if ev == + NodeCreated { + node_key: node_keys[i], + provider_id: providers_ids[i], + rent_per_month: ctx.rent_per_v_node, + node_params: node_params[i].clone() + }) + ); + } + + // CDN node created event + for i in 0..3 { + assert!(matches!(events.pop().unwrap(), Event::CdnNodeCreated(ev) if ev == + CdnNodeCreated { + cdn_node_key: cdn_node_keys[i], + provider_id: providers_ids[i], + cdn_node_params: cdn_node_params[i].clone(), + undistributed_payment: 0 + }) + ); + } + + // Cluster created event + assert!( + matches!(events.pop().unwrap(), Event::ClusterCreated(ev) if ev == + ClusterCreated { + cluster_id: ctx.cluster_id, + manager: ctx.manager_id, + cluster_params: ctx.cluster_params.clone() + }) + ); + + // Permission granted event + for provider_id in providers_ids { + assert!( + matches!(events.pop().unwrap(), Event::PermissionGranted(ev) if ev == + PermissionGranted { + account_id: ctx.manager_id, + permission: Permission::ClusterManagerTrustedBy(*provider_id) + }) + ); + } + + // Cluster storage node added event + for i in 0..3 { + assert!(matches!(events.pop().unwrap(), Event::ClusterNodeAdded(ev) if ev == + ClusterNodeAdded { + cluster_id: ctx.cluster_id, + node_key: node_keys[i] + }) + ); + } + + // Cluster cdn node added event + for i in 0..3 { + assert!(matches!(events.pop().unwrap(), Event::ClusterCdnNodeAdded(ev) if ev == + ClusterCdnNodeAdded { + cluster_id: ctx.cluster_id, + cdn_node_key: cdn_node_keys[i] + }) + ); + } + + // Cluster resource reserved event + assert!( + matches!(events.pop().unwrap(), Event::ClusterReserveResource(ev) if ev == + ClusterReserveResource { + cluster_id: ctx.cluster_id, + resource: ctx.reserved_resource + }) + ); + + assert_eq!(events.len(), 0, "All events must be checked"); + +} + + +#[ink::test] +fn cluster_add_node_err_if_node_in_cluster() { + let mut ctx = setup_cluster(); + + let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + set_balance(another_manager_id, 1000 * TOKEN); + + set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); + let another_cluster_id = ctx.contract.cluster_create( + ClusterParams::from("{}") + )?; + + assert_eq!( + ctx.contract.cluster_add_node( + another_cluster_id, + ctx.node_key1, + ctx.v_nodes1, + ), + Err(NodeIsAddedToCluster(ctx.cluster_id)) + ); +} + + +#[ink::test] +fn cluster_add_node_err_if_not_trusted_manager() { + let mut ctx = setup_cluster(); + + let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + set_balance(another_manager_id, 1000 * TOKEN); + + set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); + let another_cluster_id = ctx.contract.cluster_create( + ClusterParams::from("{}") + )?; + + let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + set_balance(new_provider_id, 1000 * TOKEN); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + let new_node_key = ctx.contract.node_create( + new_node_key, + NodeParams::from("new_node"), + 1000, + 100 + )?; + + let new_v_nodes: Vec = vec![10, 11, 12]; + set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); + assert_eq!( + ctx.contract.cluster_add_node( + another_cluster_id, + new_node_key, + new_v_nodes, + ), + Err(OnlyTrustedClusterManager) + ); +} + + +#[ink::test] +fn cluster_add_node_err_if_not_cluster_manager() { + let mut ctx = setup_cluster(); + + let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + set_balance(another_manager_id, 1000 * TOKEN); + + set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); + let another_cluster_id = ctx.contract.cluster_create( + ClusterParams::from("{}") + )?; + + let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + set_balance(new_provider_id, 1000 * TOKEN); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + let new_node_key = ctx.contract.node_create( + new_node_key, + NodeParams::from("new_node"), + 1000, + 100 + )?; + + let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_manager_id, 1000 * TOKEN); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + ctx.contract.grant_trusted_manager_permission(not_manager_id)?; + + let new_v_nodes: Vec = vec![10, 11, 12]; + set_caller_value(not_manager_id, CONTRACT_FEE_LIMIT); + assert_eq!( + ctx.contract.cluster_add_node( + another_cluster_id, + new_node_key, + new_v_nodes, + ), + Err(OnlyClusterManager) + ); +} + + +#[ink::test] +fn cluster_add_node_success() { + let mut ctx = setup_cluster(); + + let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + set_balance(new_provider_id, 1000 * TOKEN); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_node_rent_per_month = 100; + let new_node_params = NodeParams::from("new_node"); + let new_node_capacity = 1000; + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + let new_node_key = ctx.contract.node_create( + new_node_key, + new_node_params.clone(), + new_node_capacity, + new_node_rent_per_month + )?; + + assert!( + matches!(get_events().pop().unwrap(), Event::NodeCreated(ev) if ev == + NodeCreated { + node_key: new_node_key, + provider_id: new_provider_id, + rent_per_month: new_node_rent_per_month, + node_params: new_node_params + }) + ); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + ctx.contract.grant_trusted_manager_permission(ctx.manager_id)?; + + assert!( + matches!( + get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == + PermissionGranted { + account_id: ctx.manager_id, + permission: Permission::ClusterManagerTrustedBy(new_provider_id) + } + ) + ); + + let new_v_nodes: Vec = vec![10, 11, 12]; + set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); + ctx.contract.cluster_add_node( + ctx.cluster_id, + new_node_key, + new_v_nodes.clone() + )?; + + assert!( + matches!(get_events().pop().unwrap(), Event::ClusterNodeAdded(ev) if ev == + ClusterNodeAdded { + cluster_id: ctx.cluster_id, + node_key: new_node_key + }) + ); + + let nodes_keys = vec![ + ctx.node_key0, + ctx.node_key1, + ctx.node_key2, + new_node_key, + ]; + + let cluster_v_nodes = vec![ + ctx.v_nodes0, + ctx.v_nodes1, + ctx.v_nodes2, + new_v_nodes + ]; + + let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; + cluster_info.cluster_v_nodes.sort(); + assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); + assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); +} + + +#[ink::test] +fn cluster_remove_node_success() { + let mut ctx = setup_cluster(); + + set_caller(ctx.manager_id); + ctx.contract.cluster_remove_node( + ctx.cluster_id, + ctx.node_key1 + )?; + + assert!( + matches!(get_events().pop().unwrap(), Event::ClusterNodeRemoved(ev) if ev == + ClusterNodeRemoved { + cluster_id: ctx.cluster_id, + node_key: ctx.node_key1 + }) + ); + + set_caller(ctx.provider_id1); + ctx.contract.node_remove(ctx.node_key1)?; + + assert!( + matches!(get_events().pop().unwrap(), Event::NodeRemoved(ev) if ev == + NodeRemoved { + node_key: ctx.node_key1 + }) + ); + + let nodes_keys = vec![ + ctx.node_key0, + ctx.node_key2, + ]; + + let cluster_v_nodes = vec![ + ctx.v_nodes0, + ctx.v_nodes2, + ]; + + let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; + cluster_info.cluster_v_nodes.sort(); + assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); + assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); + +} + + +#[ink::test] +fn cluster_set_params_err_if_not_cluster_manager() { + let ctx = &mut setup_cluster(); + + let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_manager_id, 1000 * TOKEN); + // Change params. + let new_cluster_params = NodeParams::from("new cluster params"); + set_caller_value(not_manager_id, CONTRACT_FEE_LIMIT); + + assert_eq!( + ctx.contract.cluster_set_params( + ctx.cluster_id, + new_cluster_params + ), + Err(OnlyClusterManager) + ); +} + + +#[ink::test] +fn cluster_set_params_success() { + let mut ctx = setup_cluster(); + + // Change params. + let new_cluster_params = NodeParams::from("new cluster params"); + set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); + ctx.contract.cluster_set_params(ctx.cluster_id, new_cluster_params.clone())?; + + // Check the changed params. + let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; + assert_eq!(cluster_info.cluster.cluster_params, new_cluster_params); +} + + +#[ink::test] +fn cluster_replace_node_err_if_not_cluster_manager() { + let mut ctx = setup_cluster(); + + let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_caller_value(not_manager_id, 0); + + // Reassign a vnode from node1 to node2. + assert_eq!( + ctx.contract.cluster_replace_node( + ctx.cluster_id, + vec![1, 2, 3], + ctx.node_key2 + ), + Err(OnlyClusterManager) + ); +} + + +#[ink::test] +fn cluster_replace_node_err_if_node_does_not_exist() { + let mut ctx = setup_cluster(); + + let bad_node_key = AccountId::from([0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, 0x9c, 0x76]); + set_caller(ctx.manager_id); + assert_eq!( + ctx.contract + .cluster_replace_node( + ctx.cluster_id, + vec![1, 2, 3], + bad_node_key + ), + Err(NodeDoesNotExist) + ); +} + + +#[ink::test] +fn cluster_replace_node_success() { + let mut ctx = setup_cluster(); + + set_caller(ctx.manager_id); + // Reassign a vnode from node0 to node2. + ctx.contract.cluster_replace_node( + ctx.cluster_id, + vec![1, 3], + ctx.node_key2 + )?; + + // Check the last event + let ev = get_events().pop().unwrap(); + assert!(matches!(ev, Event::ClusterNodeReplaced(ev) if ev == + ClusterNodeReplaced { + cluster_id: ctx.cluster_id, + node_key: ctx.node_key2 + } + )); + + let mut cluster_v_nodes = Vec::::new(); + cluster_v_nodes.extend(vec![2]); + cluster_v_nodes.extend(ctx.v_nodes1.clone()); + cluster_v_nodes.extend(ctx.v_nodes2.clone()); + cluster_v_nodes.extend(vec![1, 3]); + cluster_v_nodes.sort(); + + let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; + cluster_info.cluster_v_nodes.sort(); + assert_eq!(&cluster_info.cluster_v_nodes, &cluster_v_nodes, "a v_node must be replaced"); + + let mut v_nodes0 = ctx.contract.get_v_nodes_by_node(ctx.node_key0.clone()); + v_nodes0.sort(); + let mut v_nodes1 = ctx.contract.get_v_nodes_by_node(ctx.node_key1.clone()); + v_nodes1.sort(); + let mut v_nodes2 = ctx.contract.get_v_nodes_by_node(ctx.node_key2.clone()); + v_nodes2.sort(); + + assert_eq!(&v_nodes0, &vec![2], "v_nodes must be replaced for the 1st node"); + assert_eq!(&v_nodes1, &vec![4, 5, 6], "v_nodes must not be replaced for the 2nd node"); + assert_eq!(&v_nodes2, &vec![1, 3, 7, 8, 9], "v_nodes must be assigned to the 3rd node"); + + // Check the changed state of the nodes. + let expected_resources = [ + (ctx.node_key0, 100 - 10), + (ctx.node_key1, 100 - 10 - 10 - 10), + (ctx.node_key2, 100 - 10 - 10 - 10 - 10 - 10), + ]; + + for (node_key, available) in expected_resources { + let node_info = ctx.contract.node_get(node_key).unwrap(); + assert_eq!( + node_info.node.free_resource, available, + "resources must have shifted between nodes" + ); + } +} + + +#[ink::test] +fn cluster_reserve_resource_success() { + let mut ctx = setup_cluster(); + set_caller(ctx.manager_id); + + // Reserve more resources. + ctx.contract.cluster_reserve_resource(ctx.cluster_id, 5); + + // Check the last event. + let ev = get_events().pop().unwrap(); + assert!(matches!(ev, Event::ClusterReserveResource(ev) if ev == + ClusterReserveResource { + cluster_id: ctx.cluster_id, + resource: 5 + } + )); + + // Check the changed state of the cluster. + let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; + assert_eq!(cluster.resource_per_v_node, 10 + 5); + + // Check the changed state of the nodes. + let expected_resources = [ + (ctx.node_key0, 100 - 40 - 5), + (ctx.node_key1, 100 - 40 - 5), + (ctx.node_key2, 100 - 40 - 5), + ]; + for (node_id, available) in expected_resources { + assert_eq!( + ctx.contract.node_get(node_id)?.node.free_resource, + available, + "more resources must be reserved from the nodes" + ); + } +} + + +#[ink::test] +fn cluster_distribute_revenue_success() { + let ctx = &mut setup_cluster(); + let test_bucket = &setup_bucket(ctx); + // Go to the future when some revenues are due. + advance_block::(); + // Pay the due thus far. + set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); + ctx.contract.bucket_settle_payment(test_bucket.bucket_id); + + // Get state before the distribution. + let to_distribute = ctx + .contract + .cluster_get(ctx.cluster_id)? + .cluster + .revenues + .peek(); + + let before0 = balance_of(ctx.provider_id0); + let before1 = balance_of(ctx.provider_id1); + let before2 = balance_of(ctx.provider_id2); + let before_mgmt = balance_of(ctx.manager_id); + + let skip_events = get_events::().len(); + + // Set a network fee. + let network_fee_bp = 100; // 1% + let cluster_management_fee_bp = 200; // 2% + set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); + ctx.contract.admin_set_fee_config(FeeConfig { + network_fee_bp, + network_fee_destination: AccountId::default(), + cluster_management_fee_bp, + }); + + let burned_fee = to_distribute * network_fee_bp / 10_000; + let manager_fee = (to_distribute - burned_fee) * cluster_management_fee_bp / 10_000; + let provider_fee: u128 = (to_distribute - burned_fee - manager_fee) / 3; + + // Distribute the revenues of the cluster to providers. + ctx.contract.cluster_distribute_revenues(ctx.cluster_id); + + // Check the last events. + let mut events = get_events(); + events.reverse(); // Work with pop(). + events.truncate(events.len() - skip_events); + let expected_recipients = vec![ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; + + for provider_id in expected_recipients { + assert!( + matches!(events.pop().unwrap(), Event::ClusterDistributeRevenues(ev) if ev == + ClusterDistributeRevenues { + cluster_id: ctx.cluster_id, + provider_id + }) + ); + } + + assert_eq!(events.len(), 0, "all events must be checked"); + + // Get state after the distribution. + let rounding_error = ctx + .contract + .cluster_get(ctx.cluster_id)? + .cluster + .revenues + .peek(); + + let earned0 = balance_of(ctx.provider_id0) - before0; + let earned1 = balance_of(ctx.provider_id1) - before1; + let earned2 = balance_of(ctx.provider_id2) - before2; + let earned_mgmt = balance_of(ctx.manager_id) - before_mgmt; + + assert!(provider_fee > 0, "provider must earn something"); + assert_eq!( + earned0, provider_fee, + "providers must earn the correct amount" + ); + assert_eq!( + earned1, provider_fee, + "providers must earn the correct amount" + ); + assert_eq!( + earned2, provider_fee, + "providers must earn the correct amount" + ); + + assert!(burned_fee > 0, "the network must earn something"); + assert!(manager_fee > 0, "the manager_id must earn something"); + assert_eq!( + earned_mgmt, manager_fee, + "the manager_id must earn the correct amount" + ); + + assert!(to_distribute > 0); + assert!( + rounding_error < 10, + "revenues must go out of the cluster (besides rounding)" + ); + assert_eq!( + earned0 + earned1 + earned2 + burned_fee + manager_fee + rounding_error, + to_distribute, + "all revenues must go to providers" + ); +} + + +#[ink::test] +fn cluster_distribute_cdn_revenue_success() { + // todo: this test scenario must be revised as it does pure printing without any assertion + println!("Creating new cdn cluster"); + + let mut ctx = setup_cluster(); + + // The provider stops trusting the manager_id. + println!("Cluster id is {}", ctx.cluster_id); + set_caller(ctx.provider_id0); + + let usd_per_cere = TOKEN / 100; + set_caller(admin_id()); + ctx.contract.account_set_usd_per_cere(usd_per_cere); + + let usd_amount = ctx.contract.account_get_usd_per_cere(); + println!("Current usd amount is {}", usd_amount); + + let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); + println!("The current rate is {}", rate); + + let usd_per_kb = rate / KB_PER_GB; + println!("The current rate per kb {}", usd_per_kb); + + let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); + println!("The current cere rate per kb {}", cere_per_kb); + + set_caller_value(ctx.provider_id0, 10 * TOKEN); + ctx.contract.account_deposit(); + + set_caller_value(ctx.provider_id0, 10 * TOKEN); + ctx.contract.account_bond(5 * TOKEN); + + set_caller(ctx.provider_id0); + ctx.contract.set_fee_bp(1_000); + + let account0_before_putting = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); + println!("Before putting revenue: {:?}", account0_before_putting); + + ctx.contract.cluster_put_cdn_revenue( + ctx.cluster_id, + vec![(ctx.provider_id0, 1000), (ctx.provider_id0, 541643)], + vec![(ctx.cdn_node_key0, 1000), (ctx.cdn_node_key1, 541643)], + vec![], + 5, + ); + let account0_after_putting = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); + println!("After putting revenue: {:?}", account0_after_putting); + + let cluster_list_1 = ctx.contract.cluster_list(0, 10, None); + println!("Cluster list one {:?}", cluster_list_1); + let cdn_node0 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key0).unwrap(); + let cdn_node1 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key1).unwrap(); + + println!("{:?}", cdn_node0); + println!("{:?}", cdn_node1); + let cluster0 = ctx.contract.clusters.get(ctx.cluster_id); + println!("{:?}", cluster0); + let cluster_list = ctx.contract.cluster_list(0, 10, None); + println!("{:?}", cluster0); + println!("{:?}", cluster_list); + + let validated_commit_node0 = ctx.contract.get_validated_commit(ctx.cdn_node_key0); + println!("Validated commit: {:?}", validated_commit_node0); + + let fee = ctx.contract.get_fee_bp(); + println!("Protocol fee in basis points: {:?}", fee); + + let protocol_revenues = ctx.contract.get_protocol_revenues(); + println!("Protocol revenues: {:?}", protocol_revenues); + + set_caller(ctx.provider_id0); + + ctx.contract.cluster_distribute_cdn_revenue(ctx.cluster_id); + + let cdn_node0 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key0).unwrap(); + let cdn_node1 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key1).unwrap(); + println!("{:?}", cdn_node0); + println!("{:?}", cdn_node1); + + let cdn_cluster_list = ctx.contract.cluster_list(0, 10, None); + println!("{:?}", cdn_cluster_list); + + let account0_after_distributing = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); + println!("{:?}", account0_after_distributing); + +} diff --git a/bucket/ddc_bucket/tests/test_contract.rs b/bucket/ddc_bucket/tests/test_contract.rs deleted file mode 100644 index 1e759e43..00000000 --- a/bucket/ddc_bucket/tests/test_contract.rs +++ /dev/null @@ -1,1592 +0,0 @@ -use ink_lang as ink; - -use crate::ddc_bucket::account::entity::Account; -use crate::ddc_bucket::cluster::entity::ClusterInfo; -use crate::ddc_bucket::flow::Flow; -use crate::ddc_bucket::node::entity::{NodeStatusInCluster, NodeKey}; -use crate::ddc_bucket::schedule::{Schedule, MS_PER_MONTH}; -use crate::ddc_bucket::Error::*; -use crate::ddc_bucket::*; - -use super::env_utils::*; - -fn setup() -> DdcBucket { - set_caller(admin_id()); - set_callee(contract_id()); - let contract = DdcBucket::new(); - set_balance(contract_id(), 10); - contract -} - -const KB_PER_GB: Balance = 1_048_576; - -struct TestCluster { - contract: DdcBucket, - - provider_id0: AccountId, - provider_id1: AccountId, - provider_id2: AccountId, - - node_key0: NodeKey, - node_key1: NodeKey, - node_key2: NodeKey, - node_params0: NodeParams, - node_params1: NodeParams, - node_params2: NodeParams, - v_nodes0: Vec, - v_nodes1: Vec, - v_nodes2: Vec, - - cdn_node_key0: CdnNodeKey, - cdn_node_key1: CdnNodeKey, - cdn_node_key2: CdnNodeKey, - cdn_node_params0: CdnNodeParams, - cdn_node_params1: CdnNodeParams, - cdn_node_params2: CdnNodeParams, - - manager_id: AccountId, - cluster_id: ClusterId, - cluster_params: ClusterParams, - cluster_v_nodes: Vec, - nodes_keys: Vec, - cdn_nodes_keys: Vec, - rent_per_v_node: Balance, - capacity: u32, - reserved_resource: u32, -} - -fn new_cluster() -> TestCluster { - - let mut contract: DdcBucket = setup(); - - let provider_id0 = AccountId::from([0xae, 0x7d, 0xe8, 0x17, 0xa4, 0xa5, 0x12, 0x57, 0xd2, 0x49, 0x64, 0x28, 0x3b, 0x25, 0x69, 0x09, 0xdf, 0x0c, 0x99, 0x97, 0xc0, 0x3e, 0x2b, 0x88, 0x02, 0x02, 0xee, 0x10, 0xf4, 0x4d, 0x72, 0x48]); - let provider_id1 = AccountId::from([0xc4, 0xba, 0xfd, 0x6a, 0xa1, 0x5a, 0x14, 0xd6, 0xee, 0xf2, 0xea, 0x92, 0xb7, 0xc6, 0x84, 0x51, 0x68, 0x39, 0xbe, 0x96, 0xd6, 0xbf, 0xca, 0xa3, 0x68, 0xd2, 0x4f, 0xff, 0x09, 0x85, 0xa7, 0x1e]); - let provider_id2 = AccountId::from([0xfa, 0x01, 0x28, 0xf8, 0xe1, 0x32, 0xc6, 0x81, 0x21, 0x06, 0xa5, 0xce, 0xae, 0x6d, 0xcf, 0xf3, 0xd2, 0xc0, 0x1b, 0xb0, 0x13, 0xf2, 0xd7, 0x75, 0x6f, 0x20, 0xf9, 0x50, 0x00, 0xd6, 0xc7, 0x2b]); - let manager_id = AccountId::from([0xd2, 0xc5, 0xea, 0xa2, 0x0c, 0xd0, 0x4e, 0xfb, 0x3f, 0x10, 0xb8, 0xad, 0xa9, 0xa4, 0x4f, 0xe0, 0x85, 0x41, 0x1f, 0x59, 0xf2, 0x34, 0x1a, 0x92, 0xa3, 0x48, 0x4f, 0x04, 0x51, 0x87, 0x68, 0x54]); - - set_balance(provider_id0, 1000 * TOKEN); - set_balance(provider_id1, 1000 * TOKEN); - set_balance(provider_id2, 1000 * TOKEN); - set_balance(manager_id, 1000 * TOKEN); - - let rent_per_v_node: Balance = 10 * TOKEN; - let reserved_resource = 10; - let capacity = 100; - - - // Create the 1st storage node - let node_key0 = AccountId::from([0x0a; 32]); - let node_params0 = NodeParams::from("{\"url\":\"https://ddc.cere.network/storage/0\"}"); - let capacity0 = capacity; - set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); - contract.node_create( - node_key0, - node_params0.clone(), - capacity0, - rent_per_v_node - ).unwrap(); - - - // Create the 2nd storage node - let node_key1 = AccountId::from([0x0b; 32]); - let node_params1 = NodeParams::from("{\"url\":\"https://ddc-1.cere.network/storage/1\"}"); - let capacity1 = capacity; - set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); - contract.node_create( - node_key1, - node_params1.clone(), - capacity1, - rent_per_v_node - ).unwrap(); - - - // Create the 3rd storage node - let node_key2 = AccountId::from([0x0c; 32]); - let node_params2 = NodeParams::from("{\"url\":\"https://ddc-2.cere.network/storage/2\"}"); - let capacity2 = capacity; - set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); - let node_key2 = contract.node_create( - node_key2, - node_params2.clone(), - capacity2, - rent_per_v_node, - ).unwrap(); - - - // Create the 1st cdn node - let cdn_node_key0 = AccountId::from([0x0d; 32]); - let cdn_node_params0 = CdnNodeParams::from("{\"url\":\"https://ddc.cere.network/cdn/0\"}"); - set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); - contract.cdn_node_create( - cdn_node_key0, - cdn_node_params0.clone() - ).unwrap(); - - - // Create the 2nd cdn node - let cdn_node_key1 = AccountId::from([0x0e; 32]); - let cdn_node_params1 = CdnNodeParams::from("{\"url\":\"https://ddc.cere.network/cdn/1\"}"); - set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); - contract.cdn_node_create( - cdn_node_key1, - cdn_node_params1.clone() - ).unwrap(); - - - // Create the 3rd cdn node - let cdn_node_key2 = AccountId::from([0x0f; 32]); - let cdn_node_params2 = CdnNodeParams::from("{\"url\":\"https://ddc.cere.network/cdn/2\"}"); - set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); - contract.cdn_node_create( - cdn_node_key2, - cdn_node_params2.clone() - ).unwrap(); - - - // Create a Cluster - let cluster_params = ClusterParams::from("{}"); - set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - let cluster_id = contract.cluster_create( - cluster_params.clone(), - ).unwrap(); - - - // Grant trusted manager_id permission from node providers to the cluster manager_id - for provider_id in [provider_id0, provider_id1, provider_id2] { - set_caller_value(provider_id, CONTRACT_FEE_LIMIT); - contract.grant_trusted_manager_permission(manager_id).unwrap(); - let expected_perm = Permission::ClusterManagerTrustedBy(provider_id); - assert!(contract.has_permission(manager_id, expected_perm)); - } - - - // Add the 1st storage node to the Cluster - let v_nodes0 = vec![1, 2, 3]; - set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - contract.cluster_add_node( - cluster_id, - node_key0, - v_nodes0.clone() - ).unwrap(); - - - // Add the 2nd storage node to the Cluster - let v_nodes1 = vec![4, 5, 6]; - set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - contract.cluster_add_node( - cluster_id, - node_key1, - v_nodes1.clone() - ).unwrap(); - - - // Add the 3rd storage node to the Cluster - let v_nodes2 = vec![7, 8, 9]; - set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - contract.cluster_add_node( - cluster_id, - node_key2, - v_nodes2.clone() - ).unwrap(); - - - // Add the 1st cdn node to the Cluster - set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - contract.cluster_add_cdn_node( - cluster_id, - cdn_node_key0, - ).unwrap(); - - - // Add the 2nd cdn node to the Cluster - set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - contract.cluster_add_cdn_node( - cluster_id, - cdn_node_key1, - ).unwrap(); - - - // Add the 3rd cdn node to the Cluster - set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - contract.cluster_add_cdn_node( - cluster_id, - cdn_node_key2, - ).unwrap(); - - - set_caller(manager_id); - contract.cluster_reserve_resource(cluster_id, reserved_resource); - - - let nodes_keys = vec![ - node_key0, - node_key1, - node_key2 - ]; - - let cdn_nodes_keys = vec![ - cdn_node_key0, - cdn_node_key1, - cdn_node_key2 - ]; - - let mut cluster_v_nodes = Vec::::new(); - cluster_v_nodes.extend(v_nodes0.clone()); - cluster_v_nodes.extend(v_nodes1.clone()); - cluster_v_nodes.extend(v_nodes2.clone()); - - TestCluster { - contract, - - provider_id0, - provider_id1, - provider_id2, - - node_key0, - node_key1, - node_key2, - node_params0, - node_params1, - node_params2, - v_nodes0, - v_nodes1, - v_nodes2, - - cdn_node_key0, - cdn_node_key1, - cdn_node_key2, - cdn_node_params0, - cdn_node_params1, - cdn_node_params2, - - manager_id, - cluster_id, - cluster_params, - cluster_v_nodes, - rent_per_v_node, - nodes_keys, - cdn_nodes_keys, - capacity, - reserved_resource, - } -} - - -struct TestBucket { - bucket_id: BucketId, - owner_id: AccountId, - resource: u32, -} - -fn new_bucket(ctx: &mut TestCluster) -> TestBucket { - let owner_id = AccountId::from([0xd4, 0x8f, 0x63, 0x67, 0xe2, 0x15, 0x51, 0xdf, 0x11, 0x1c, 0x92, 0x69, 0x0d, 0x04, 0x3f, 0x75, 0xcb, 0x39, 0xf8, 0x27, 0xbb, 0xc7, 0x46, 0x4b, 0x8d, 0x5d, 0x70, 0xd1, 0x02, 0xaa, 0x71, 0x0a]); - set_balance(owner_id, 1000 * TOKEN); - set_caller_value(owner_id, CONTRACT_FEE_LIMIT); - - let bucket_id = ctx.contract.bucket_create( - "{}".to_string(), - ctx.cluster_id, - None - ); - - // Reserve some resources for the bucket from the cluster. - set_caller_value(owner_id, CONTRACT_FEE_LIMIT); - let resource = 1; - ctx.contract.bucket_alloc_into_cluster(bucket_id, resource); - - // Deposit some value to pay for buckets. - set_caller_value(owner_id, 10 * TOKEN); - ctx.contract.account_deposit(); - - TestBucket { - bucket_id, - owner_id, - resource, - } -} - - -#[ink::test] -fn cluster_create_works() { - let ctx = new_cluster(); - let providers_ids = &[ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; - let node_keys = &[ctx.node_key0, ctx.node_key1, ctx.node_key2]; - let cdn_node_keys = &[ctx.cdn_node_key0, ctx.cdn_node_key1, ctx.cdn_node_key2]; - let node_params = &[ctx.node_params0.clone(), ctx.node_params1.clone(), ctx.node_params2.clone()]; - let cdn_node_params = &[ctx.cdn_node_params0.clone(), ctx.cdn_node_params1.clone(), ctx.cdn_node_params2.clone()]; - - assert_eq!(ctx.cluster_id, 0, "cluster_id must start at 0"); - - // Check cluster nodes - { - let node0 = ctx.contract.node_get(ctx.node_key0)?; - let v_nodes0 = ctx.contract.get_v_nodes_by_node(ctx.node_key0); - - assert_eq!( - node0, - NodeInfo { - node_key: ctx.node_key0, - node: Node { - provider_id: ctx.provider_id0, - rent_per_month: ctx.rent_per_v_node, - free_resource: ctx.capacity - ctx.reserved_resource * 3, - node_params: ctx.node_params0.clone(), - cluster_id: Some(ctx.cluster_id), - status_in_cluster: Some(NodeStatusInCluster::ADDING), - }, - v_nodes: v_nodes0 - } - ); - - let node1 = ctx.contract.node_get(ctx.node_key1)?; - let v_nodes1 = ctx.contract.get_v_nodes_by_node(ctx.node_key1); - - assert_eq!( - node1, - NodeInfo { - node_key: ctx.node_key1, - node: Node { - provider_id: ctx.provider_id1, - rent_per_month: ctx.rent_per_v_node, - free_resource: ctx.capacity - ctx.reserved_resource * 3, - node_params: ctx.node_params1.clone(), - cluster_id: Some(ctx.cluster_id), - status_in_cluster: Some(NodeStatusInCluster::ADDING), - }, - v_nodes: v_nodes1 - } - ); - - let node2 = ctx.contract.node_get(ctx.node_key2)?; - let v_nodes2 = ctx.contract.get_v_nodes_by_node(ctx.node_key2); - - assert_eq!( - node2, - NodeInfo { - node_key: ctx.node_key2, - node: Node { - provider_id: ctx.provider_id2, - rent_per_month: ctx.rent_per_v_node, - free_resource: ctx.capacity - ctx.reserved_resource * 3, - node_params: ctx.node_params2.clone(), - cluster_id: Some(ctx.cluster_id), - status_in_cluster: Some(NodeStatusInCluster::ADDING), - }, - v_nodes: v_nodes2 - } - ); - } - - // Check the cluster - { - let cluster = ctx.contract.cluster_get(ctx.cluster_id)?; - let cluster_v_nodes = ctx.contract.get_v_nodes_by_cluster(ctx.cluster_id); - assert_eq!( - cluster, - ClusterInfo { - cluster_id: ctx.cluster_id, - cluster: Cluster { - manager_id: ctx.manager_id, - nodes_keys: ctx.nodes_keys, - resource_per_v_node: ctx.reserved_resource, - resource_used: 0, - cluster_params: ctx.cluster_params.clone(), - revenues: Cash(0), - total_rent: ctx.rent_per_v_node * ctx.cluster_v_nodes.len() as Balance, - cdn_nodes_keys: ctx.cdn_nodes_keys, - cdn_usd_per_gb: 104_857_600, - cdn_revenues: Cash(0), - }, - cluster_v_nodes - } - ); - } - - // Check emitted events - let mut events = get_events(); - events.reverse(); // Work with pop(). - - // Storage node created event - for i in 0..3 { - assert!(matches!(events.pop().unwrap(), Event::NodeCreated(ev) if ev == - NodeCreated { - node_key: node_keys[i], - provider_id: providers_ids[i], - rent_per_month: ctx.rent_per_v_node, - node_params: node_params[i].clone() - }) - ); - } - - // CDN node created event - for i in 0..3 { - assert!(matches!(events.pop().unwrap(), Event::CdnNodeCreated(ev) if ev == - CdnNodeCreated { - cdn_node_key: cdn_node_keys[i], - provider_id: providers_ids[i], - cdn_node_params: cdn_node_params[i].clone(), - undistributed_payment: 0 - }) - ); - } - - // Cluster created event - assert!( - matches!(events.pop().unwrap(), Event::ClusterCreated(ev) if ev == - ClusterCreated { - cluster_id: ctx.cluster_id, - manager: ctx.manager_id, - cluster_params: ctx.cluster_params.clone() - }) - ); - - // Permission granted event - for provider_id in providers_ids { - assert!( - matches!(events.pop().unwrap(), Event::PermissionGranted(ev) if ev == - PermissionGranted { - account_id: ctx.manager_id, - permission: Permission::ClusterManagerTrustedBy(*provider_id) - }) - ); - } - - // Cluster storage node added event - for i in 0..3 { - assert!(matches!(events.pop().unwrap(), Event::ClusterNodeAdded(ev) if ev == - ClusterNodeAdded { - cluster_id: ctx.cluster_id, - node_key: node_keys[i] - }) - ); - } - - // Cluster cdn node added event - for i in 0..3 { - assert!(matches!(events.pop().unwrap(), Event::ClusterCdnNodeAdded(ev) if ev == - ClusterCdnNodeAdded { - cluster_id: ctx.cluster_id, - cdn_node_key: cdn_node_keys[i] - }) - ); - } - - // Cluster resource reserved event - assert!( - matches!(events.pop().unwrap(), Event::ClusterReserveResource(ev) if ev == - ClusterReserveResource { - cluster_id: ctx.cluster_id, - resource: ctx.reserved_resource - }) - ); - - assert_eq!(events.len(), 0, "All events must be checked"); - -} - - -#[ink::test] -fn cluster_node_add_err_if_node_in_cluster() { - let mut ctx = new_cluster(); - - let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); - set_balance(another_manager_id, 1000 * TOKEN); - - set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - let another_cluster_id = ctx.contract.cluster_create( - ClusterParams::from("{}") - )?; - - assert_eq!( - ctx.contract.cluster_add_node( - another_cluster_id, - ctx.node_key1, - ctx.v_nodes1, - ), - Err(NodeIsAddedToCluster(ctx.cluster_id)) - ); -} - - -#[ink::test] -fn cluster_node_add_err_if_not_trusted_manager() { - let mut ctx = new_cluster(); - - let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); - set_balance(another_manager_id, 1000 * TOKEN); - - set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - let another_cluster_id = ctx.contract.cluster_create( - ClusterParams::from("{}") - )?; - - let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); - set_balance(new_provider_id, 1000 * TOKEN); - - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); - - set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - let new_node_key = ctx.contract.node_create( - new_node_key, - NodeParams::from("new_node"), - 1000, - 100 - )?; - - let new_v_nodes: Vec = vec![10, 11, 12]; - set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - assert_eq!( - ctx.contract.cluster_add_node( - another_cluster_id, - new_node_key, - new_v_nodes, - ), - Err(OnlyTrustedClusterManager) - ); -} - - -#[ink::test] -fn cluster_node_add_err_if_not_cluster_manager() { - let mut ctx = new_cluster(); - - let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); - set_balance(another_manager_id, 1000 * TOKEN); - - set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - let another_cluster_id = ctx.contract.cluster_create( - ClusterParams::from("{}") - )?; - - let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); - set_balance(new_provider_id, 1000 * TOKEN); - - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); - - set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - let new_node_key = ctx.contract.node_create( - new_node_key, - NodeParams::from("new_node"), - 1000, - 100 - )?; - - let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); - set_balance(not_manager_id, 1000 * TOKEN); - - set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.grant_trusted_manager_permission(not_manager_id)?; - - let new_v_nodes: Vec = vec![10, 11, 12]; - set_caller_value(not_manager_id, CONTRACT_FEE_LIMIT); - assert_eq!( - ctx.contract.cluster_add_node( - another_cluster_id, - new_node_key, - new_v_nodes, - ), - Err(OnlyClusterManager) - ); -} - - - -#[ink::test] -fn cluster_node_add_success() { - let mut ctx = new_cluster(); - - let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); - set_balance(new_provider_id, 1000 * TOKEN); - - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); - let new_node_rent_per_month = 100; - let new_node_params = NodeParams::from("new_node"); - let new_node_capacity = 1000; - - set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - let new_node_key = ctx.contract.node_create( - new_node_key, - new_node_params.clone(), - new_node_capacity, - new_node_rent_per_month - )?; - - assert!( - matches!(get_events().pop().unwrap(), Event::NodeCreated(ev) if ev == - NodeCreated { - node_key: new_node_key, - provider_id: new_provider_id, - rent_per_month: new_node_rent_per_month, - node_params: new_node_params - }) - ); - - set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.grant_trusted_manager_permission(ctx.manager_id)?; - - assert!( - matches!( - get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == - PermissionGranted { - account_id: ctx.manager_id, - permission: Permission::ClusterManagerTrustedBy(new_provider_id) - } - ) - ); - - let new_v_nodes: Vec = vec![10, 11, 12]; - set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); - ctx.contract.cluster_add_node( - ctx.cluster_id, - new_node_key, - new_v_nodes.clone() - )?; - - assert!( - matches!(get_events().pop().unwrap(), Event::ClusterNodeAdded(ev) if ev == - ClusterNodeAdded { - cluster_id: ctx.cluster_id, - node_key: new_node_key - }) - ); - - let nodes_keys = vec![ - ctx.node_key0, - ctx.node_key1, - ctx.node_key2, - new_node_key, - ]; - - let cluster_v_nodes = vec![ - ctx.v_nodes0, - ctx.v_nodes1, - ctx.v_nodes2, - new_v_nodes - ]; - - let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; - cluster_info.cluster_v_nodes.sort(); - assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); - assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); -} - - -#[ink::test] -fn node_remove_err_if_not_provider() { - let mut ctx = new_cluster(); - - let not_provider = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); - set_balance(not_provider, 1000 * TOKEN); - - set_caller(not_provider); - assert_eq!( - ctx.contract.node_remove( - ctx.node_key1, - ), - Err(OnlyNodeProvider) - ); -} - - -#[ink::test] -fn node_remove_err_if_node_in_cluster() { - let mut ctx = new_cluster(); - - set_caller(ctx.provider_id1); - assert_eq!( - ctx.contract.node_remove( - ctx.node_key1, - ), - Err(NodeIsAddedToCluster(ctx.cluster_id)) - ); -} - - -#[ink::test] -fn cluster_node_remove_works() { - let mut ctx = new_cluster(); - - set_caller(ctx.manager_id); - ctx.contract.cluster_remove_node( - ctx.cluster_id, - ctx.node_key1 - )?; - - assert!( - matches!(get_events().pop().unwrap(), Event::ClusterNodeRemoved(ev) if ev == - ClusterNodeRemoved { - cluster_id: ctx.cluster_id, - node_key: ctx.node_key1 - }) - ); - - set_caller(ctx.provider_id1); - ctx.contract.node_remove(ctx.node_key1)?; - - assert!( - matches!(get_events().pop().unwrap(), Event::NodeRemoved(ev) if ev == - NodeRemoved { - node_key: ctx.node_key1 - }) - ); - - let nodes_keys = vec![ - ctx.node_key0, - ctx.node_key2, - ]; - - let cluster_v_nodes = vec![ - ctx.v_nodes0, - ctx.v_nodes2, - ]; - - let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; - cluster_info.cluster_v_nodes.sort(); - assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); - assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); - -} - - -#[ink::test] -fn cluster_replace_node_only_manager() { - let mut ctx = new_cluster(); - - let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); - set_caller_value(not_manager_id, 0); - - // Reassign a vnode from node1 to node2. - assert_eq!( - ctx.contract.cluster_replace_node( - ctx.cluster_id, - vec![1, 2, 3], - ctx.node_key2 - ), - Err(OnlyClusterManager) - ); -} - -#[ink::test] -fn cluster_replace_node_works() { - let mut ctx = new_cluster(); - - set_caller(ctx.manager_id); - // Reassign a vnode from node0 to node2. - ctx.contract.cluster_replace_node( - ctx.cluster_id, - vec![1, 3], - ctx.node_key2 - )?; - - // Check the last event - let ev = get_events().pop().unwrap(); - assert!(matches!(ev, Event::ClusterNodeReplaced(ev) if ev == - ClusterNodeReplaced { - cluster_id: ctx.cluster_id, - node_key: ctx.node_key2 - } - )); - - let mut cluster_v_nodes = Vec::::new(); - cluster_v_nodes.extend(vec![2]); - cluster_v_nodes.extend(ctx.v_nodes1.clone()); - cluster_v_nodes.extend(ctx.v_nodes2.clone()); - cluster_v_nodes.extend(vec![1, 3]); - cluster_v_nodes.sort(); - - let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; - cluster_info.cluster_v_nodes.sort(); - assert_eq!(&cluster_info.cluster_v_nodes, &cluster_v_nodes, "a v_node must be replaced"); - - let mut v_nodes0 = ctx.contract.get_v_nodes_by_node(ctx.node_key0.clone()); - v_nodes0.sort(); - let mut v_nodes1 = ctx.contract.get_v_nodes_by_node(ctx.node_key1.clone()); - v_nodes1.sort(); - let mut v_nodes2 = ctx.contract.get_v_nodes_by_node(ctx.node_key2.clone()); - v_nodes2.sort(); - - assert_eq!(&v_nodes0, &vec![2], "v_nodes must be replaced for the 1st node"); - assert_eq!(&v_nodes1, &vec![4, 5, 6], "v_nodes must not be replaced for the 2nd node"); - assert_eq!(&v_nodes2, &vec![1, 3, 7, 8, 9], "v_nodes must be assigned to the 3rd node"); - - // Check the changed state of the nodes. - let expected_resources = [ - (ctx.node_key0, 100 - 10), - (ctx.node_key1, 100 - 10 - 10 - 10), - (ctx.node_key2, 100 - 10 - 10 - 10 - 10 - 10), - ]; - - for (node_key, available) in expected_resources { - let node_info = ctx.contract.node_get(node_key).unwrap(); - assert_eq!( - node_info.node.free_resource, available, - "resources must have shifted between nodes" - ); - } -} - - -#[ink::test] -fn cluster_reserve_works() { - let mut ctx = new_cluster(); - set_caller(ctx.manager_id); - - // Reserve more resources. - ctx.contract.cluster_reserve_resource(ctx.cluster_id, 5); - - // Check the last event. - let ev = get_events().pop().unwrap(); - assert!(matches!(ev, Event::ClusterReserveResource(ev) if ev == - ClusterReserveResource { - cluster_id: ctx.cluster_id, - resource: 5 - } - )); - - // Check the changed state of the cluster. - let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; - assert_eq!(cluster.resource_per_v_node, 10 + 5); - - // Check the changed state of the nodes. - let expected_resources = [ - (ctx.node_key0, 100 - 40 - 5), - (ctx.node_key1, 100 - 40 - 5), - (ctx.node_key2, 100 - 40 - 5), - ]; - for (node_id, available) in expected_resources { - assert_eq!( - ctx.contract.node_get(node_id)?.node.free_resource, - available, - "more resources must be reserved from the nodes" - ); - } -} - - -#[ink::test] -fn cluster_management_validation_works() { - let mut ctx = new_cluster(); - - let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); - set_balance(not_manager_id, 1000 * TOKEN); - - set_caller(not_manager_id); - assert_eq!( - ctx.contract.cluster_replace_node( - ctx.cluster_id, - vec![1, 2, 3], - ctx.node_key1.clone() - ), - Err(OnlyClusterManager), - "only the manager_id can modify the cluster" - ); - - let bad_node_id = AccountId::from([0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, 0x9c, 0x76]); - set_caller(ctx.manager_id); - assert_eq!( - ctx.contract - .cluster_replace_node( - ctx.cluster_id, - vec![1, 2, 3], - bad_node_id - ), - Err(NodeDoesNotExist), - "cluster replacement node must exist" - ); - -} - -#[ink::test] -fn cdn_cluster_gas_converter_works() { - println!("Creating new cdn cluster"); - - let mut ctx = new_cluster(); - - // The provider stops trusting the manager_id. - println!("Cdn cluster id is {}", ctx.cluster_id); - set_caller(ctx.manager_id); - ctx.contract.cdn_set_rate(ctx.cluster_id, 3_750_000_000); - set_caller(ctx.provider_id0); - let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); - - let usd_per_cere = TOKEN / 100; - set_caller(admin_id()); - ctx.contract.account_set_usd_per_cere(usd_per_cere); - - let usd_amount = ctx.contract.account_get_usd_per_cere(); - println!("Current usd amount is {}", usd_amount); - - println!("The current rate is {}", rate); - - let usd_per_kb = rate / KB_PER_GB; - println!("The current rate per kb {}", usd_per_kb); - - let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); - println!("The current cere rate per kb {}", cere_per_kb); -} - - -#[ink::test] -fn cdn_cluster_payment_works() { - // todo: this test scenario must be revised as it does pure printing without any assertion - println!("Creating new cdn cluster"); - - let mut ctx = new_cluster(); - - // The provider stops trusting the manager_id. - println!("Cluster id is {}", ctx.cluster_id); - set_caller(ctx.provider_id0); - - let usd_per_cere = TOKEN / 100; - set_caller(admin_id()); - ctx.contract.account_set_usd_per_cere(usd_per_cere); - - let usd_amount = ctx.contract.account_get_usd_per_cere(); - println!("Current usd amount is {}", usd_amount); - - let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); - println!("The current rate is {}", rate); - - let usd_per_kb = rate / KB_PER_GB; - println!("The current rate per kb {}", usd_per_kb); - - let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); - println!("The current cere rate per kb {}", cere_per_kb); - - set_caller_value(ctx.provider_id0, 10 * TOKEN); - ctx.contract.account_deposit(); - - set_caller_value(ctx.provider_id0, 10 * TOKEN); - ctx.contract.account_bond(5 * TOKEN); - - set_caller(ctx.provider_id0); - ctx.contract.set_fee_bp(1_000); - - let account0_before_putting = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); - println!("Before putting revenue: {:?}", account0_before_putting); - - ctx.contract.cluster_put_cdn_revenue( - ctx.cluster_id, - vec![(ctx.provider_id0, 1000), (ctx.provider_id0, 541643)], - vec![(ctx.cdn_node_key0, 1000), (ctx.cdn_node_key1, 541643)], - vec![], - 5, - ); - let account0_after_putting = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); - println!("After putting revenue: {:?}", account0_after_putting); - - let cluster_list_1 = ctx.contract.cluster_list(0, 10, None); - println!("Cluster list one {:?}", cluster_list_1); - let cdn_node0 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key0).unwrap(); - let cdn_node1 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key1).unwrap(); - - println!("{:?}", cdn_node0); - println!("{:?}", cdn_node1); - let cluster0 = ctx.contract.clusters.get(ctx.cluster_id); - println!("{:?}", cluster0); - let cluster_list = ctx.contract.cluster_list(0, 10, None); - println!("{:?}", cluster0); - println!("{:?}", cluster_list); - - let validated_commit_node0 = ctx.contract.get_validated_commit(ctx.cdn_node_key0); - println!("Validated commit: {:?}", validated_commit_node0); - - let fee = ctx.contract.get_fee_bp(); - println!("Protocol fee in basis points: {:?}", fee); - - let protocol_revenues = ctx.contract.get_protocol_revenues(); - println!("Protocol revenues: {:?}", protocol_revenues); - - set_caller(ctx.provider_id0); - - ctx.contract.cluster_distribute_cdn_revenue(ctx.cluster_id); - - let cdn_node0 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key0).unwrap(); - let cdn_node1 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key1).unwrap(); - println!("{:?}", cdn_node0); - println!("{:?}", cdn_node1); - - let cdn_cluster_list = ctx.contract.cluster_list(0, 10, None); - println!("{:?}", cdn_cluster_list); - - let account0_after_distributing = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); - println!("{:?}", account0_after_distributing); - -} - -fn bucket_settle_payment(ctx: &mut TestCluster, test_bucket: &TestBucket) { - // Go to the future when some revenues are due. - advance_block::(); - // Pay the due thus far. - set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); - ctx.contract.bucket_settle_payment(test_bucket.bucket_id); -} - -#[ink::test] -fn bucket_pays_cluster() { - let ctx = &mut new_cluster(); - let test_bucket = &new_bucket(ctx); - do_bucket_pays_cluster(ctx, test_bucket, 1).unwrap(); -} - -#[ink::test] -fn bucket_pays_cluster_at_new_rate() { - let ctx = &mut new_cluster(); - - let test_bucket = &new_bucket(ctx); - // Set up an exchange rate manager_id. - set_caller(admin_id()); - ctx.contract - .admin_grant_permission(admin_id(), Permission::SetExchangeRate).unwrap(); - - - // Change the currency exchange rate. - let usd_per_cere = 2; - set_caller(admin_id()); - ctx.contract.account_set_usd_per_cere(usd_per_cere * TOKEN); - - do_bucket_pays_cluster(ctx, test_bucket, usd_per_cere).unwrap(); -} - -fn do_bucket_pays_cluster( - ctx: &mut TestCluster, - test_bucket: &TestBucket, - usd_per_cere: Balance, -) -> Result<()> { - let expected_rent = ctx.rent_per_v_node * ctx.cluster_v_nodes.len() as Balance; - - // Check the state before payment. - let before = ctx - .contract - .account_get(test_bucket.owner_id)? - .deposit - .peek(); - let bucket = ctx.contract.bucket_get(test_bucket.bucket_id)?.bucket; - assert_eq!(bucket.owner_id, test_bucket.owner_id); - /* TODO: Not testable at the moment, see struct BucketInStatus. - assert_eq!(bucket.flow, - Flow { - from: test_bucket.owner_id, - schedule: Schedule::new(0, expected_rent), - }); - */ - let timestamp_before = block_timestamp::(); - bucket_settle_payment(ctx, &test_bucket); - let timestamp_after = block_timestamp::(); - - // Check the last event. - let ev = get_events().pop().unwrap(); - assert!(matches!(ev, Event::BucketSettlePayment(ev) if ev == - BucketSettlePayment { - bucket_id: test_bucket.bucket_id, - cluster_id: ctx.cluster_id - } - )); - - // Check the state after payment. - let after = ctx - .contract - .account_get(test_bucket.owner_id)? - .deposit - .peek(); - let spent = before - after; - /* TODO: Not testable at the moment, see struct BucketInStatus. - let bucket = ctx.contract.bucket_get(test_bucket.bucket_id)?.bucket; - assert_eq!(bucket.flow, - Flow { - from: test_bucket.owner_id, - schedule: Schedule::new(BLOCK_TIME, expected_rent), - }); - */ - let timespan = timestamp_after - timestamp_before; - let expect_revenues_usd = expected_rent * timespan as u128 / MS_PER_MONTH as u128; - let expect_revenues = expect_revenues_usd / usd_per_cere; - assert!(expect_revenues > 0); - assert_eq!( - expect_revenues, spent, - "revenues must come from the bucket owner" - ); - - let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; - assert_eq!( - cluster.revenues.peek(), - expect_revenues, - "must get revenues into the cluster" - ); - - Ok(()) -} - - -#[ink::test] -fn cluster_pays_providers() { - let ctx = &mut new_cluster(); - let test_bucket = &new_bucket(ctx); - bucket_settle_payment(ctx, &test_bucket); - - // Get state before the distribution. - let to_distribute = ctx - .contract - .cluster_get(ctx.cluster_id)? - .cluster - .revenues - .peek(); - - let before0 = balance_of(ctx.provider_id0); - let before1 = balance_of(ctx.provider_id1); - let before2 = balance_of(ctx.provider_id2); - let before_mgmt = balance_of(ctx.manager_id); - - let skip_events = get_events::().len(); - - // Set a network fee. - let network_fee_bp = 100; // 1% - let cluster_management_fee_bp = 200; // 2% - set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); - ctx.contract.admin_set_fee_config(FeeConfig { - network_fee_bp, - network_fee_destination: AccountId::default(), - cluster_management_fee_bp, - }); - - let burned_fee = to_distribute * network_fee_bp / 10_000; - let manager_fee = (to_distribute - burned_fee) * cluster_management_fee_bp / 10_000; - let provider_fee: u128 = (to_distribute - burned_fee - manager_fee) / 3; - - // Distribute the revenues of the cluster to providers. - ctx.contract.cluster_distribute_revenues(ctx.cluster_id); - - // Check the last events. - let mut events = get_events(); - events.reverse(); // Work with pop(). - events.truncate(events.len() - skip_events); - let expected_recipients = vec![ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; - - for provider_id in expected_recipients { - assert!( - matches!(events.pop().unwrap(), Event::ClusterDistributeRevenues(ev) if ev == - ClusterDistributeRevenues { - cluster_id: ctx.cluster_id, - provider_id - }) - ); - } - - assert_eq!(events.len(), 0, "all events must be checked"); - - // Get state after the distribution. - let rounding_error = ctx - .contract - .cluster_get(ctx.cluster_id)? - .cluster - .revenues - .peek(); - - let earned0 = balance_of(ctx.provider_id0) - before0; - let earned1 = balance_of(ctx.provider_id1) - before1; - let earned2 = balance_of(ctx.provider_id2) - before2; - let earned_mgmt = balance_of(ctx.manager_id) - before_mgmt; - - assert!(provider_fee > 0, "provider must earn something"); - assert_eq!( - earned0, provider_fee, - "providers must earn the correct amount" - ); - assert_eq!( - earned1, provider_fee, - "providers must earn the correct amount" - ); - assert_eq!( - earned2, provider_fee, - "providers must earn the correct amount" - ); - - assert!(burned_fee > 0, "the network must earn something"); - assert!(manager_fee > 0, "the manager_id must earn something"); - assert_eq!( - earned_mgmt, manager_fee, - "the manager_id must earn the correct amount" - ); - - assert!(to_distribute > 0); - assert!( - rounding_error < 10, - "revenues must go out of the cluster (besides rounding)" - ); - assert_eq!( - earned0 + earned1 + earned2 + burned_fee + manager_fee + rounding_error, - to_distribute, - "all revenues must go to providers" - ); -} - - -#[ink::test] -fn bucket_create_works() { - let ctx = &mut new_cluster(); - let test_bucket = &new_bucket(ctx); - - // Check the structure of the bucket including the payment flow. - let total_rent = ctx.rent_per_v_node * ctx.cluster_v_nodes.len() as Balance; - let expect_bucket = Bucket { - owner_id: test_bucket.owner_id, - cluster_id: ctx.cluster_id, - flow: Flow { - from: test_bucket.owner_id, - schedule: Schedule::new(0, total_rent), - }, - resource_reserved: test_bucket.resource, - public_availability: false, - resource_consumption_cap: 0, - }; - - // Check the status of the bucket. - let bucket_status = ctx.contract.bucket_get(test_bucket.bucket_id)?; - assert_eq!( - bucket_status, - BucketStatus { - bucket_id: test_bucket.bucket_id, - bucket: expect_bucket.into(), - params: "{}".to_string(), - writer_ids: vec![test_bucket.owner_id], - reader_ids: vec![], - rent_covered_until_ms: 297600000, // TODO: check this value. - } - ); - - let mut events = get_events(); - events.reverse(); // Work with pop(). - events.truncate(8 - 3 - 2); // Skip 3 NodeCreated and 2 cluster setup events. - - // Create bucket. - assert!( - matches!(events.pop().unwrap(), Event::BucketCreated(ev) if ev == - BucketCreated { bucket_id: test_bucket.bucket_id, owner_id: test_bucket.owner_id }) - ); - - assert!( - matches!(events.pop().unwrap(), Event::BucketAllocated(ev) if ev == - BucketAllocated { bucket_id: test_bucket.bucket_id, cluster_id: ctx.cluster_id, resource: test_bucket.resource }) - ); - - // Deposit more. - let net_deposit = 10 * TOKEN; - assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == - Deposit { account_id: test_bucket.owner_id, value: net_deposit })); - - assert_eq!(events.len(), 0, "all events must be checked"); -} - - -#[ink::test] -fn account_deposit_works() { - let account_id = AccountId::from([0x76, 0x95, 0x7c, 0xa6, 0xbe, 0xf5, 0xa3, 0x6d, 0x67, 0x0d, 0x3a, 0x84, 0xc6, 0x0a, 0xe2, 0xbb, 0xc9, 0x5e, 0xee, 0xde, 0x3a, 0x5f, 0x27, 0x0e, 0x26, 0xe3, 0x43, 0x4c, 0x46, 0xe2, 0x98, 0x10]); - set_balance(account_id, 1000 * TOKEN); - - let mut contract = setup(); - - assert_eq!( - contract.account_get(account_id), - Err(AccountDoesNotExist), - "must not get a non-existent account" - ); - - let deposit = 10 * TOKEN; - let deposit_after_fee = deposit; - - // Deposit some value. - set_caller_value(account_id, deposit); - contract.account_deposit(); - - let account = contract.account_get(account_id)?; - assert_eq!( - account, - Account { - deposit: Cash(deposit_after_fee), - payable_schedule: Schedule::empty(), - bonded: Cash(0), - unbonded_amount: Cash(0), - negative: Cash(0), - unbonded_timestamp: 0, - }, - "must take deposit minus creation fee" - ); - - // Deposit more value. - set_caller_value(account_id, deposit); - contract.account_deposit(); - - let account = contract.account_get(account_id)?; - assert_eq!( - account, - Account { - deposit: Cash(deposit_after_fee + deposit), - payable_schedule: Schedule::empty(), - bonded: Cash(0), - unbonded_amount: Cash(0), - negative: Cash(0), - unbonded_timestamp: 0, - }, - "must take more deposits without creation fee" - ); - - // Check events. - let mut events = get_events(); - events.reverse(); // Work with pop(). - - // First deposit event. - assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == - Deposit { account_id, value: deposit_after_fee })); - - // Second deposit event. No deposit_contract_fee because the account already exists. - assert!(matches!(events.pop().unwrap(), Event::Deposit(ev) if ev == - Deposit { account_id, value: deposit })); - - assert_eq!(events.len(), 0, "all events must be checked"); -} - - -#[ink::test] -fn node_set_params_works() { - let mut ctx = new_cluster(); - - // Change params. - let new_node_params = NodeParams::from("new node params"); - set_caller_value(ctx.provider_id0, CONTRACT_FEE_LIMIT); - ctx.contract.node_set_params(ctx.node_key0, new_node_params.clone())?; - - // Check the changed params. - let status = ctx.contract.node_get(ctx.node_key0)?; - assert_eq!(status.node.node_params, new_node_params); -} - -#[ink::test] -fn node_set_params_only_owner() { - let mut ctx = new_cluster(); - - let not_provider = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); - set_balance(not_provider, 1000 * TOKEN); - // Change params.not_provider - let new_node_params = NodeParams::from("new node params"); - set_caller_value(not_provider, CONTRACT_FEE_LIMIT); - - assert_eq!( - ctx.contract.node_set_params( - ctx.node_key0, - new_node_params - ), - Err(OnlyNodeProvider) - ); -} - -#[ink::test] -fn cluster_change_params_works() { - let mut ctx = new_cluster(); - - // Change params. - let new_cluster_params = NodeParams::from("new cluster params"); - set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); - ctx.contract.cluster_set_params(ctx.cluster_id, new_cluster_params.clone())?; - - // Check the changed params. - let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; - assert_eq!(cluster_info.cluster.cluster_params, new_cluster_params); -} - -#[ink::test] -fn cluster_change_params_only_owner() { - let ctx = &mut new_cluster(); - - let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); - set_balance(not_manager_id, 1000 * TOKEN); - // Change params. - let new_cluster_params = NodeParams::from("new cluster params"); - set_caller_value(not_manager_id, CONTRACT_FEE_LIMIT); - - assert_eq!( - ctx.contract.cluster_set_params( - ctx.cluster_id, - new_cluster_params - ), - Err(OnlyClusterManager) - ); -} - -#[ink::test] -fn bucket_change_params_works() { - let ctx = &mut new_cluster(); - let test_bucket = &new_bucket(ctx); - - // Change params. - set_caller_value(test_bucket.owner_id, CONTRACT_FEE_LIMIT); - ctx.contract - .bucket_change_params(test_bucket.bucket_id, "new params".to_string()); - - // Check the changed params. - let status = ctx.contract.bucket_get(test_bucket.bucket_id)?; - assert_eq!(status.params, "new params"); -} - -#[ink::test] -#[should_panic] -fn bucket_change_params_only_owner() { - let ctx = &mut new_cluster(); - let test_bucket = &new_bucket(ctx); - - // Change params. - set_caller_value(get_accounts().bob, CONTRACT_FEE_LIMIT); - ctx.contract - .bucket_change_params(test_bucket.bucket_id, "new params".to_string()); - // Panic. -} - -#[ink::test] -fn bucket_list_works() { - let mut ddc_bucket = setup(); - - let owner_id1 = AccountId::from([0xd8, 0x69, 0x19, 0x54, 0xea, 0xdc, 0x9a, 0xc0, 0x3d, 0x37, 0x56, 0x9f, 0x2a, 0xe8, 0xdf, 0x59, 0x34, 0x3f, 0x32, 0x65, 0xba, 0xd4, 0x16, 0xac, 0x07, 0xdf, 0x06, 0xeb, 0x4d, 0xbc, 0x6a, 0x66]); - set_balance(owner_id1, 1000 * TOKEN); - let owner_id2 = AccountId::from([0x2a, 0x5f, 0xbc, 0xcf, 0x71, 0x0b, 0x65, 0x04, 0x88, 0x91, 0x12, 0x7e, 0x5e, 0xe3, 0x78, 0xdb, 0x48, 0x63, 0x09, 0x44, 0xcc, 0xc5, 0x75, 0xbd, 0xa5, 0xaa, 0xa5, 0x0e, 0x77, 0xab, 0x7b, 0x4e]); - set_balance(owner_id2, 1000 * TOKEN); - let owner_id3 = AccountId::from([0x64, 0xef, 0xd7, 0xb4, 0x41, 0xb2, 0x58, 0xb5, 0x56, 0x6b, 0xfc, 0x4b, 0x19, 0xb8, 0xe5, 0x09, 0x5d, 0x17, 0xb3, 0xc3, 0x44, 0x38, 0x58, 0xa9, 0x7d, 0x20, 0x49, 0x39, 0xbd, 0xbd, 0xb6, 0x48]); - set_balance(owner_id3, 1000 * TOKEN); - - let cluster_id = 0; - - set_caller_value(owner_id1, CONTRACT_FEE_LIMIT); - let bucket_id1 = ddc_bucket.bucket_create("".to_string(), cluster_id, None); - let bucket_status1 = ddc_bucket.bucket_get(bucket_id1).unwrap(); - - set_caller_value(owner_id2, CONTRACT_FEE_LIMIT); - let bucket_id2 = ddc_bucket.bucket_create("".to_string(), cluster_id, None); - let bucket_status2 = ddc_bucket.bucket_get(bucket_id2)?; - - assert_ne!(bucket_id1, bucket_id2); - let count = 2; - - assert_eq!( - ddc_bucket.bucket_list(0, 100, None), - (vec![bucket_status1.clone(), bucket_status2.clone()], count) - ); - - assert_eq!( - ddc_bucket.bucket_list(0, 2, None), - (vec![bucket_status1.clone(), bucket_status2.clone()], count) - ); - - assert_eq!( - ddc_bucket.bucket_list(0, 1, None), - ( - vec![bucket_status1.clone()], - count - ) - ); - assert_eq!( - ddc_bucket.bucket_list(1, 1, None), - ( - vec![bucket_status2.clone()], - count - ) - ); - - assert_eq!(ddc_bucket.bucket_list(count, 20, None), (vec![], count)); - - // Filter by owner. - assert_eq!( - ddc_bucket.bucket_list(0, 100, Some(owner_id1)), - ( - vec![bucket_status1.clone()], - count - ) - ); - - assert_eq!( - ddc_bucket.bucket_list(0, 100, Some(owner_id2)), - ( - vec![bucket_status2.clone()], - count - ) - ); - - assert_eq!( - ddc_bucket.bucket_list(0, 100, Some(owner_id3)), - (vec![], count) - ); -} - - -#[ink::test] -fn node_list_works() { - let ctx = new_cluster(); - - let node_info = ctx.contract.node_get(ctx.node_key1)?; - assert_eq!(ctx.provider_id1, node_info.node.provider_id.clone()); - - let node1 = NodeInfo { - node_key: ctx.node_key1, - node: Node { - provider_id: ctx.provider_id1, - rent_per_month: ctx.rent_per_v_node, - free_resource: ctx.capacity - ctx.reserved_resource * 3, - cluster_id: Some(ctx.cluster_id), - status_in_cluster: Some(NodeStatusInCluster::ADDING), - node_params: ctx.node_params1, - }, - v_nodes: ctx.v_nodes1.clone() - }; - - let node2 = NodeInfo { - node_key: ctx.node_key2, - node: Node { - provider_id:ctx.provider_id2, - rent_per_month: ctx.rent_per_v_node, - free_resource: ctx.capacity - ctx.reserved_resource * 3, - cluster_id: Some(ctx.cluster_id), - status_in_cluster: Some(NodeStatusInCluster::ADDING), - node_params: ctx.node_params2, - }, - v_nodes: ctx.v_nodes2.clone() - }; - - let count = 3; - - assert_eq!( - ctx.contract.node_list(1, 100, None), - (vec![node1.clone(), node2.clone()], count) - ); - - assert_eq!( - ctx.contract.node_list(1, 2, None), - (vec![node1.clone(), node2.clone()], count) - ); - - assert_eq!( - ctx.contract.node_list(1, 1, None), - (vec![node1.clone() /*, node2.clone()*/], count) - ); - - assert_eq!( - ctx.contract.node_list(2, 1, None), - (vec![/*node1.clone(),*/ node2.clone()], count) - ); - - assert_eq!(ctx.contract.node_list(21, 20, None), (vec![], count)); - - // Filter by owner. - assert_eq!( - ctx.contract.node_list(1, 100, Some(ctx.provider_id1)), - (vec![node1.clone() /*, node2.clone()*/], count) - ); - - assert_eq!( - ctx.contract.node_list(1, 100, Some(ctx.provider_id2)), - (vec![/*node1.clone(),*/ node2.clone()], count) - ); - - let not_provider= AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); - - assert_eq!( - ctx.contract.node_list(1, 100, Some(not_provider)), - (vec![], count) - ); -} diff --git a/bucket/ddc_bucket/tests/test_currency.rs b/bucket/ddc_bucket/tests/test_currency.rs index 91e7e5eb..9cd99e3f 100644 --- a/bucket/ddc_bucket/tests/test_currency.rs +++ b/bucket/ddc_bucket/tests/test_currency.rs @@ -1,21 +1,13 @@ use ink_lang as ink; use crate::ddc_bucket::*; - use super::env_utils::*; +use super::setup_utils::*; -fn setup() -> DdcBucket { - set_caller(admin_id()); - set_callee(contract_id()); - let mut contract = DdcBucket::new(); - set_balance(contract_id(), CONTRACT_FEE_LIMIT); - contract.admin_grant_permission(admin_id(), Permission::SetExchangeRate).unwrap(); - contract -} #[ink::test] -fn currency_conversion_init_works() { - let contract = setup(); +fn currency_conversion_init_success() { + let contract = setup_contract(); let usd_amount = contract.account_get_usd_per_cere(); println!("{}", usd_amount); assert_eq!( @@ -25,9 +17,10 @@ fn currency_conversion_init_works() { ); } + #[ink::test] -fn currency_conversion_set_rate_works() { - let mut contract = setup(); +fn currency_conversion_set_rate_success() { + let mut contract = setup_contract(); let usd_per_cere = TOKEN / 10; println!("{}", usd_per_cere); @@ -41,12 +34,44 @@ fn currency_conversion_set_rate_works() { ); } + #[ink::test] #[should_panic] fn currency_conversion_set_rate_only_admin() { - let mut contract = setup(); + let mut contract = setup_contract(); let not_admin = get_accounts().bob; set_caller(not_admin); contract.account_set_usd_per_cere(9); } + + +#[ink::test] +fn converter_success() { + // todo: this test scenario must be revised as it does pure printing without any assertion + println!("Creating new cdn cluster"); + + let mut ctx = setup_cluster(); + + // The provider stops trusting the manager_id. + println!("Cdn cluster id is {}", ctx.cluster_id); + set_caller(ctx.manager_id); + ctx.contract.cdn_set_rate(ctx.cluster_id, 3_750_000_000); + set_caller(ctx.provider_id0); + let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); + + let usd_per_cere = TOKEN / 100; + set_caller(admin_id()); + ctx.contract.account_set_usd_per_cere(usd_per_cere); + + let usd_amount = ctx.contract.account_get_usd_per_cere(); + println!("Current usd amount is {}", usd_amount); + + println!("The current rate is {}", rate); + + let usd_per_kb = rate / KB_PER_GB; + println!("The current rate per kb {}", usd_per_kb); + + let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); + println!("The current cere rate per kb {}", cere_per_kb); +} diff --git a/bucket/ddc_bucket/tests/test_node.rs b/bucket/ddc_bucket/tests/test_node.rs new file mode 100644 index 00000000..514d6dd5 --- /dev/null +++ b/bucket/ddc_bucket/tests/test_node.rs @@ -0,0 +1,149 @@ +use ink_lang as ink; + +use crate::ddc_bucket::Error::*; +use crate::ddc_bucket::*; +use super::env_utils::*; +use super::setup_utils::*; + + +#[ink::test] +fn node_remove_err_if_not_provider() { + let mut ctx = setup_cluster(); + + let not_provider = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_provider, 1000 * TOKEN); + + set_caller(not_provider); + assert_eq!( + ctx.contract.node_remove( + ctx.node_key1, + ), + Err(OnlyNodeProvider) + ); +} + + +#[ink::test] +fn node_remove_err_if_node_in_cluster() { + let mut ctx = setup_cluster(); + + set_caller(ctx.provider_id1); + assert_eq!( + ctx.contract.node_remove( + ctx.node_key1, + ), + Err(NodeIsAddedToCluster(ctx.cluster_id)) + ); +} + + +#[ink::test] +fn node_set_params_err_if_not_provider() { + let mut ctx = setup_cluster(); + + let not_provider = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_provider, 1000 * TOKEN); + // Change params.not_provider + let new_node_params = NodeParams::from("new node params"); + set_caller_value(not_provider, CONTRACT_FEE_LIMIT); + + assert_eq!( + ctx.contract.node_set_params( + ctx.node_key0, + new_node_params + ), + Err(OnlyNodeProvider) + ); +} + + +#[ink::test] +fn node_set_params_success() { + let mut ctx = setup_cluster(); + + // Change params. + let new_node_params = NodeParams::from("new node params"); + set_caller_value(ctx.provider_id0, CONTRACT_FEE_LIMIT); + ctx.contract.node_set_params(ctx.node_key0, new_node_params.clone())?; + + // Check the changed params. + let status = ctx.contract.node_get(ctx.node_key0)?; + assert_eq!(status.node.node_params, new_node_params); +} + + +#[ink::test] +fn node_list_success() { + let ctx = setup_cluster(); + + let node_info = ctx.contract.node_get(ctx.node_key1)?; + assert_eq!(ctx.provider_id1, node_info.node.provider_id.clone()); + + let node1 = NodeInfo { + node_key: ctx.node_key1, + node: Node { + provider_id: ctx.provider_id1, + rent_per_month: ctx.rent_per_v_node, + free_resource: ctx.capacity - ctx.reserved_resource * 3, + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + node_params: ctx.node_params1, + }, + v_nodes: ctx.v_nodes1.clone() + }; + + let node2 = NodeInfo { + node_key: ctx.node_key2, + node: Node { + provider_id:ctx.provider_id2, + rent_per_month: ctx.rent_per_v_node, + free_resource: ctx.capacity - ctx.reserved_resource * 3, + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + node_params: ctx.node_params2, + }, + v_nodes: ctx.v_nodes2.clone() + }; + + let count = 3; + + assert_eq!( + ctx.contract.node_list(1, 100, None), + (vec![node1.clone(), node2.clone()], count) + ); + + assert_eq!( + ctx.contract.node_list(1, 2, None), + (vec![node1.clone(), node2.clone()], count) + ); + + assert_eq!( + ctx.contract.node_list(1, 1, None), + (vec![node1.clone() /*, node2.clone()*/], count) + ); + + assert_eq!( + ctx.contract.node_list(2, 1, None), + (vec![/*node1.clone(),*/ node2.clone()], count) + ); + + assert_eq!(ctx.contract.node_list(21, 20, None), (vec![], count)); + + // Filter by owner. + assert_eq!( + ctx.contract.node_list(1, 100, Some(ctx.provider_id1)), + (vec![node1.clone() /*, node2.clone()*/], count) + ); + + assert_eq!( + ctx.contract.node_list(1, 100, Some(ctx.provider_id2)), + (vec![/*node1.clone(),*/ node2.clone()], count) + ); + + let not_provider= AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + + assert_eq!( + ctx.contract.node_list(1, 100, Some(not_provider)), + (vec![], count) + ); +} From 547774f89ca2a68cfdacd2ee705667be4cecba55 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 28 Jun 2023 20:18:51 +0200 Subject: [PATCH 47/89] chore(test): test for creating a node --- bucket/ddc_bucket/tests/setup_utils.rs | 12 ++--- bucket/ddc_bucket/tests/test_bucket.rs | 4 +- bucket/ddc_bucket/tests/test_cluster.rs | 12 ++--- bucket/ddc_bucket/tests/test_node.rs | 62 ++++++++++++++++++++++++- 4 files changed, 74 insertions(+), 16 deletions(-) diff --git a/bucket/ddc_bucket/tests/setup_utils.rs b/bucket/ddc_bucket/tests/setup_utils.rs index b971d7d8..2062ca4a 100644 --- a/bucket/ddc_bucket/tests/setup_utils.rs +++ b/bucket/ddc_bucket/tests/setup_utils.rs @@ -42,7 +42,7 @@ pub struct TestCluster { pub cluster_v_nodes: Vec, pub nodes_keys: Vec, pub cdn_nodes_keys: Vec, - pub rent_per_v_node: Balance, + pub rent_per_month: Balance, pub capacity: u32, pub reserved_resource: u32, } @@ -61,7 +61,7 @@ pub fn setup_cluster() -> TestCluster { set_balance(provider_id2, 1000 * TOKEN); set_balance(manager_id, 1000 * TOKEN); - let rent_per_v_node: Balance = 10 * TOKEN; + let rent_per_month: Balance = 10 * TOKEN; let reserved_resource = 10; let capacity = 100; @@ -75,7 +75,7 @@ pub fn setup_cluster() -> TestCluster { node_key0, node_params0.clone(), capacity0, - rent_per_v_node + rent_per_month ).unwrap(); @@ -88,7 +88,7 @@ pub fn setup_cluster() -> TestCluster { node_key1, node_params1.clone(), capacity1, - rent_per_v_node + rent_per_month ).unwrap(); @@ -101,7 +101,7 @@ pub fn setup_cluster() -> TestCluster { node_key2, node_params2.clone(), capacity2, - rent_per_v_node, + rent_per_month, ).unwrap(); @@ -255,7 +255,7 @@ pub fn setup_cluster() -> TestCluster { cluster_id, cluster_params, cluster_v_nodes, - rent_per_v_node, + rent_per_month, nodes_keys, cdn_nodes_keys, capacity, diff --git a/bucket/ddc_bucket/tests/test_bucket.rs b/bucket/ddc_bucket/tests/test_bucket.rs index 8c65fde8..010c7df0 100644 --- a/bucket/ddc_bucket/tests/test_bucket.rs +++ b/bucket/ddc_bucket/tests/test_bucket.rs @@ -12,7 +12,7 @@ fn do_bucket_pays_cluster( test_bucket: &TestBucket, usd_per_cere: Balance, ) -> Result<()> { - let expected_rent = ctx.rent_per_v_node * ctx.cluster_v_nodes.len() as Balance; + let expected_rent = ctx.rent_per_month * ctx.cluster_v_nodes.len() as Balance; // Check the state before payment. let before = ctx @@ -115,7 +115,7 @@ fn bucket_create_success() { let test_bucket = &setup_bucket(ctx); // Check the structure of the bucket including the payment flow. - let total_rent = ctx.rent_per_v_node * ctx.cluster_v_nodes.len() as Balance; + let total_rent = ctx.rent_per_month * ctx.cluster_v_nodes.len() as Balance; let expect_bucket = Bucket { owner_id: test_bucket.owner_id, cluster_id: ctx.cluster_id, diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 62e95188..11bf654c 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -28,7 +28,7 @@ fn cluster_create_success() { node_key: ctx.node_key0, node: Node { provider_id: ctx.provider_id0, - rent_per_month: ctx.rent_per_v_node, + rent_per_month: ctx.rent_per_month, free_resource: ctx.capacity - ctx.reserved_resource * 3, node_params: ctx.node_params0.clone(), cluster_id: Some(ctx.cluster_id), @@ -47,7 +47,7 @@ fn cluster_create_success() { node_key: ctx.node_key1, node: Node { provider_id: ctx.provider_id1, - rent_per_month: ctx.rent_per_v_node, + rent_per_month: ctx.rent_per_month, free_resource: ctx.capacity - ctx.reserved_resource * 3, node_params: ctx.node_params1.clone(), cluster_id: Some(ctx.cluster_id), @@ -66,7 +66,7 @@ fn cluster_create_success() { node_key: ctx.node_key2, node: Node { provider_id: ctx.provider_id2, - rent_per_month: ctx.rent_per_v_node, + rent_per_month: ctx.rent_per_month, free_resource: ctx.capacity - ctx.reserved_resource * 3, node_params: ctx.node_params2.clone(), cluster_id: Some(ctx.cluster_id), @@ -92,7 +92,7 @@ fn cluster_create_success() { resource_used: 0, cluster_params: ctx.cluster_params.clone(), revenues: Cash(0), - total_rent: ctx.rent_per_v_node * ctx.cluster_v_nodes.len() as Balance, + total_rent: ctx.rent_per_month * ctx.cluster_v_nodes.len() as Balance, cdn_nodes_keys: ctx.cdn_nodes_keys, cdn_usd_per_gb: 104_857_600, cdn_revenues: Cash(0), @@ -112,7 +112,7 @@ fn cluster_create_success() { NodeCreated { node_key: node_keys[i], provider_id: providers_ids[i], - rent_per_month: ctx.rent_per_v_node, + rent_per_month: ctx.rent_per_month, node_params: node_params[i].clone() }) ); @@ -303,7 +303,7 @@ fn cluster_add_node_success() { let new_node_capacity = 1000; set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - let new_node_key = ctx.contract.node_create( + ctx.contract.node_create( new_node_key, new_node_params.clone(), new_node_capacity, diff --git a/bucket/ddc_bucket/tests/test_node.rs b/bucket/ddc_bucket/tests/test_node.rs index 514d6dd5..b1bc4cac 100644 --- a/bucket/ddc_bucket/tests/test_node.rs +++ b/bucket/ddc_bucket/tests/test_node.rs @@ -6,6 +6,64 @@ use super::env_utils::*; use super::setup_utils::*; +#[ink::test] +fn node_create_err_if_node_exists() { + let mut ctx = setup_cluster(); + assert_eq!( + ctx.contract.node_create( + ctx.node_key1, + ctx.node_params1, + ctx.capacity, + ctx.rent_per_month, + ), + Err(NodeAlreadyExists) + ); +} + + +#[ink::test] +fn node_create_success() { + let mut ctx = setup_cluster(); + + let new_provider_id = AccountId::from([0x76, 0x30, 0xc6, 0x96, 0x6f, 0xd3, 0x26, 0xba, 0x1a, 0xa0, 0x6f, 0xd8, 0x7f, 0x7b, 0xf2, 0xef, 0x14, 0x11, 0xf0, 0x0d, 0x00, 0xa9, 0xe7, 0x11, 0xdf, 0xd1, 0x65, 0x14, 0x5d, 0x01, 0xdb, 0x59]); + set_balance(new_provider_id, 1000 * TOKEN); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_node_params = NodeParams::from("{\"url\":\"https://ddc-1.cere.network/storage/new\"}"); + let new_node_capacity = 100; + let new_node_rent_per_month: Balance = 10 * TOKEN; + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + ctx.contract.node_create( + new_node_key, + new_node_params.clone(), + new_node_capacity, + new_node_rent_per_month, + )?; + + assert!( + matches!(get_events().pop().unwrap(), Event::NodeCreated(ev) if ev == + NodeCreated { + node_key: new_node_key, + provider_id: new_provider_id, + rent_per_month: new_node_rent_per_month, + node_params: new_node_params.clone() + }) + ); + + let node_info = ctx.contract.node_get(new_node_key)?; + assert!(matches!(node_info.node, Node { + provider_id: new_provider_id, + rent_per_month: new_node_rent_per_month, + free_resource: new_node_capacity, + node_params: new_node_params, + cluster_id: None, + status_in_cluster: None, + })); + +} + + #[ink::test] fn node_remove_err_if_not_provider() { let mut ctx = setup_cluster(); @@ -83,7 +141,7 @@ fn node_list_success() { node_key: ctx.node_key1, node: Node { provider_id: ctx.provider_id1, - rent_per_month: ctx.rent_per_v_node, + rent_per_month: ctx.rent_per_month, free_resource: ctx.capacity - ctx.reserved_resource * 3, cluster_id: Some(ctx.cluster_id), status_in_cluster: Some(NodeStatusInCluster::ADDING), @@ -96,7 +154,7 @@ fn node_list_success() { node_key: ctx.node_key2, node: Node { provider_id:ctx.provider_id2, - rent_per_month: ctx.rent_per_v_node, + rent_per_month: ctx.rent_per_month, free_resource: ctx.capacity - ctx.reserved_resource * 3, cluster_id: Some(ctx.cluster_id), status_in_cluster: Some(NodeStatusInCluster::ADDING), From 7981ba1e9dfc545bf48f611c0f1fe6b9e91c8950 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 28 Jun 2023 21:06:44 +0200 Subject: [PATCH 48/89] chore(test): storage node test scenarios --- bucket/ddc_bucket/node/messages.rs | 2 +- bucket/ddc_bucket/tests/setup_utils.rs | 9 +-- bucket/ddc_bucket/tests/test_node.rs | 83 ++++++++++++++++++++++---- bucket/lib.rs | 2 +- 4 files changed, 77 insertions(+), 19 deletions(-) diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index 7136e43a..9708f5c5 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -35,7 +35,7 @@ impl DdcBucket { Ok(node_key) } - pub fn message_remove_node( + pub fn message_node_remove( &mut self, node_key: NodeKey ) -> Result<()> { diff --git a/bucket/ddc_bucket/tests/setup_utils.rs b/bucket/ddc_bucket/tests/setup_utils.rs index 2062ca4a..4ab88d28 100644 --- a/bucket/ddc_bucket/tests/setup_utils.rs +++ b/bucket/ddc_bucket/tests/setup_utils.rs @@ -69,12 +69,11 @@ pub fn setup_cluster() -> TestCluster { // Create the 1st storage node let node_key0 = AccountId::from([0x0a; 32]); let node_params0 = NodeParams::from("{\"url\":\"https://ddc.cere.network/storage/0\"}"); - let capacity0 = capacity; set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); contract.node_create( node_key0, node_params0.clone(), - capacity0, + capacity, rent_per_month ).unwrap(); @@ -82,12 +81,11 @@ pub fn setup_cluster() -> TestCluster { // Create the 2nd storage node let node_key1 = AccountId::from([0x0b; 32]); let node_params1 = NodeParams::from("{\"url\":\"https://ddc-1.cere.network/storage/1\"}"); - let capacity1 = capacity; set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); contract.node_create( node_key1, node_params1.clone(), - capacity1, + capacity, rent_per_month ).unwrap(); @@ -95,12 +93,11 @@ pub fn setup_cluster() -> TestCluster { // Create the 3rd storage node let node_key2 = AccountId::from([0x0c; 32]); let node_params2 = NodeParams::from("{\"url\":\"https://ddc-2.cere.network/storage/2\"}"); - let capacity2 = capacity; set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); let node_key2 = contract.node_create( node_key2, node_params2.clone(), - capacity2, + capacity, rent_per_month, ).unwrap(); diff --git a/bucket/ddc_bucket/tests/test_node.rs b/bucket/ddc_bucket/tests/test_node.rs index b1bc4cac..6e37d6b8 100644 --- a/bucket/ddc_bucket/tests/test_node.rs +++ b/bucket/ddc_bucket/tests/test_node.rs @@ -68,10 +68,10 @@ fn node_create_success() { fn node_remove_err_if_not_provider() { let mut ctx = setup_cluster(); - let not_provider = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); - set_balance(not_provider, 1000 * TOKEN); + let not_provider_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_provider_id, 1000 * TOKEN); - set_caller(not_provider); + set_caller(not_provider_id); assert_eq!( ctx.contract.node_remove( ctx.node_key1, @@ -95,6 +95,31 @@ fn node_remove_err_if_node_in_cluster() { } +#[ink::test] +fn node_remove_success() { + let mut ctx = setup_cluster(); + + set_caller(ctx.provider_id1); + ctx.contract.cluster_remove_node(ctx.cluster_id, ctx.node_key1)?; + ctx.contract.node_remove(ctx.node_key1)?; + + assert!( + matches!(get_events().pop().unwrap(), Event::NodeRemoved(ev) if ev == + NodeRemoved { + node_key: ctx.node_key1, + } + ) + ); + + assert_eq!( + ctx.contract.node_get( + ctx.node_key1, + ), + Err(NodeDoesNotExist) + ); +} + + #[ink::test] fn node_set_params_err_if_not_provider() { let mut ctx = setup_cluster(); @@ -124,12 +149,46 @@ fn node_set_params_success() { set_caller_value(ctx.provider_id0, CONTRACT_FEE_LIMIT); ctx.contract.node_set_params(ctx.node_key0, new_node_params.clone())?; + assert!( + matches!(get_events().pop().unwrap(), Event::NodeParamsSet(ev) if ev == + NodeParamsSet { + node_key: ctx.node_key0, + node_params: new_node_params.clone() + } + ) + ); + // Check the changed params. let status = ctx.contract.node_get(ctx.node_key0)?; assert_eq!(status.node.node_params, new_node_params); } +#[ink::test] +fn node_get_success() { + let ctx = setup_cluster(); + + let v_nodes1_len : u32 = ctx.v_nodes1.len().try_into().unwrap(); + assert_eq!( + ctx.contract.node_get(ctx.node_key1), + Ok({ + NodeInfo { + node_key: ctx.node_key1, + node: Node { + provider_id: ctx.provider_id1, + rent_per_month: ctx.rent_per_month, + free_resource: ctx.capacity - ctx.reserved_resource * v_nodes1_len, + node_params: ctx.node_params1, + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + v_nodes: ctx.v_nodes1 + } + }) + ); +} + + #[ink::test] fn node_list_success() { let ctx = setup_cluster(); @@ -137,12 +196,13 @@ fn node_list_success() { let node_info = ctx.contract.node_get(ctx.node_key1)?; assert_eq!(ctx.provider_id1, node_info.node.provider_id.clone()); + let v_nodes1_len : u32 = ctx.v_nodes1.len().try_into().unwrap(); let node1 = NodeInfo { node_key: ctx.node_key1, node: Node { provider_id: ctx.provider_id1, rent_per_month: ctx.rent_per_month, - free_resource: ctx.capacity - ctx.reserved_resource * 3, + free_resource: ctx.capacity - ctx.reserved_resource * v_nodes1_len, cluster_id: Some(ctx.cluster_id), status_in_cluster: Some(NodeStatusInCluster::ADDING), node_params: ctx.node_params1, @@ -150,12 +210,13 @@ fn node_list_success() { v_nodes: ctx.v_nodes1.clone() }; + let v_nodes2_len : u32 = ctx.v_nodes2.len().try_into().unwrap(); let node2 = NodeInfo { node_key: ctx.node_key2, node: Node { provider_id:ctx.provider_id2, rent_per_month: ctx.rent_per_month, - free_resource: ctx.capacity - ctx.reserved_resource * 3, + free_resource: ctx.capacity - ctx.reserved_resource * v_nodes2_len, cluster_id: Some(ctx.cluster_id), status_in_cluster: Some(NodeStatusInCluster::ADDING), node_params: ctx.node_params2, @@ -177,12 +238,12 @@ fn node_list_success() { assert_eq!( ctx.contract.node_list(1, 1, None), - (vec![node1.clone() /*, node2.clone()*/], count) + (vec![node1.clone()], count) ); assert_eq!( ctx.contract.node_list(2, 1, None), - (vec![/*node1.clone(),*/ node2.clone()], count) + (vec![node2.clone()], count) ); assert_eq!(ctx.contract.node_list(21, 20, None), (vec![], count)); @@ -190,18 +251,18 @@ fn node_list_success() { // Filter by owner. assert_eq!( ctx.contract.node_list(1, 100, Some(ctx.provider_id1)), - (vec![node1.clone() /*, node2.clone()*/], count) + (vec![node1.clone()], count) ); assert_eq!( ctx.contract.node_list(1, 100, Some(ctx.provider_id2)), - (vec![/*node1.clone(),*/ node2.clone()], count) + (vec![node2.clone()], count) ); - let not_provider= AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_provider_id= AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); assert_eq!( - ctx.contract.node_list(1, 100, Some(not_provider)), + ctx.contract.node_list(1, 100, Some(not_provider_id)), (vec![], count) ); } diff --git a/bucket/lib.rs b/bucket/lib.rs index b1c2b32a..38c76e11 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -1180,7 +1180,7 @@ pub mod ddc_bucket { &mut self, node_key: NodeKey ) -> Result<()> { - self.message_remove_node(node_key) + self.message_node_remove(node_key) } /// Sets parameters for the targeting Storage node. From f5d90ab03098c8da517f53040c07b35e87b142c4 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 28 Jun 2023 21:59:58 +0200 Subject: [PATCH 49/89] chore(test): cdn node test scenarios --- bucket/ddc_bucket/cdn_node/entity.rs | 2 +- bucket/ddc_bucket/tests/mod.rs | 1 + bucket/ddc_bucket/tests/test_cdn_node.rs | 259 +++++++++++++++++++++++ bucket/ddc_bucket/tests/test_node.rs | 4 +- bucket/lib.rs | 6 +- 5 files changed, 266 insertions(+), 6 deletions(-) create mode 100644 bucket/ddc_bucket/tests/test_cdn_node.rs diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index c6ce2a35..717cd11a 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -60,7 +60,7 @@ impl CdnNode { pub fn only_provider(&self, caller: AccountId) -> Result<()> { (self.provider_id == caller) .then(|| ()) - .ok_or(OnlyCdnNodeOwner) + .ok_or(OnlyCdnNodeProvider) } pub fn only_without_cluster(&self) -> Result<()> { diff --git a/bucket/ddc_bucket/tests/mod.rs b/bucket/ddc_bucket/tests/mod.rs index 5bf0930d..de8381fd 100644 --- a/bucket/ddc_bucket/tests/mod.rs +++ b/bucket/ddc_bucket/tests/mod.rs @@ -7,3 +7,4 @@ mod test_node; mod test_cluster; mod test_bucket; mod test_account; +mod test_cdn_node; \ No newline at end of file diff --git a/bucket/ddc_bucket/tests/test_cdn_node.rs b/bucket/ddc_bucket/tests/test_cdn_node.rs new file mode 100644 index 00000000..10602494 --- /dev/null +++ b/bucket/ddc_bucket/tests/test_cdn_node.rs @@ -0,0 +1,259 @@ +use ink_lang as ink; + +use crate::ddc_bucket::Error::*; +use crate::ddc_bucket::*; +use cdn_node::{entity::*}; + +use super::env_utils::*; +use super::setup_utils::*; + + +#[ink::test] +fn cdn_node_create_err_if_node_exists() { + let mut ctx = setup_cluster(); + assert_eq!( + ctx.contract.cdn_node_create( + ctx.cdn_node_key1, + ctx.cdn_node_params1, + ), + Err(CdnNodeAlreadyExists) + ); +} + + +#[ink::test] +fn cdn_node_create_success() { + let mut ctx = setup_cluster(); + + let new_provider_id = AccountId::from([0x76, 0x30, 0xc6, 0x96, 0x6f, 0xd3, 0x26, 0xba, 0x1a, 0xa0, 0x6f, 0xd8, 0x7f, 0x7b, 0xf2, 0xef, 0x14, 0x11, 0xf0, 0x0d, 0x00, 0xa9, 0xe7, 0x11, 0xdf, 0xd1, 0x65, 0x14, 0x5d, 0x01, 0xdb, 0x59]); + set_balance(new_provider_id, 1000 * TOKEN); + + let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_cdn_node_params = CdnNodeParams::from("{\"url\":\"https://ddc-1.cere.network/cdn/new\"}"); + let new_cdn_node_capacity = 100; + let new_cdn_node_rent_per_month: Balance = 10 * TOKEN; + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + ctx.contract.cdn_node_create( + new_cdn_node_key, + new_cdn_node_params.clone() + )?; + + assert!( + matches!(get_events().pop().unwrap(), Event::CdnNodeCreated(ev) if ev == + CdnNodeCreated { + cdn_node_key: new_cdn_node_key, + provider_id: new_provider_id, + undistributed_payment: 0, + cdn_node_params: new_cdn_node_params.clone() + }) + ); + + let cdn_node_info = ctx.contract.cdn_node_get(new_cdn_node_key)?; + assert!(matches!(cdn_node_info.cdn_node, CdnNode { + provider_id: new_provider_id, + undistributed_payment: 0, + cdn_node_params, + cluster_id: None, + status_in_cluster: None, + })); + +} + + +#[ink::test] +fn cdn_node_remove_err_if_not_provider() { + let mut ctx = setup_cluster(); + + let not_provider_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_provider_id, 1000 * TOKEN); + + set_caller(not_provider_id); + assert_eq!( + ctx.contract.cdn_node_remove( + ctx.cdn_node_key1, + ), + Err(OnlyCdnNodeProvider) + ); +} + + +#[ink::test] +fn cdn_node_remove_err_if_node_in_cluster() { + let mut ctx = setup_cluster(); + + set_caller(ctx.provider_id1); + assert_eq!( + ctx.contract.cdn_node_remove( + ctx.cdn_node_key1, + ), + Err(CdnNodeIsAddedToCluster(ctx.cluster_id)) + ); +} + + +#[ink::test] +fn cdn_node_remove_success() { + let mut ctx = setup_cluster(); + + set_caller(ctx.provider_id1); + ctx.contract.cluster_remove_cdn_node(ctx.cluster_id, ctx.cdn_node_key1)?; + ctx.contract.cdn_node_remove(ctx.cdn_node_key1)?; + + assert!( + matches!(get_events().pop().unwrap(), Event::CdnNodeRemoved(ev) if ev == + CdnNodeRemoved { + cdn_node_key: ctx.cdn_node_key1, + } + ) + ); + + assert_eq!( + ctx.contract.cdn_node_get( + ctx.cdn_node_key1, + ), + Err(CdnNodeDoesNotExist) + ); +} + + +#[ink::test] +fn cdn_node_set_params_err_if_not_provider() { + let mut ctx = setup_cluster(); + + let not_provider = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_provider, 1000 * TOKEN); + // Change params.not_provider + let new_cdn_node_params = CdnNodeParams::from("new cdn node params"); + set_caller_value(not_provider, CONTRACT_FEE_LIMIT); + + assert_eq!( + ctx.contract.cdn_node_set_params( + ctx.cdn_node_key0, + new_cdn_node_params + ), + Err(OnlyCdnNodeProvider) + ); +} + + +#[ink::test] +fn node_set_params_success() { + let mut ctx = setup_cluster(); + + // Change params. + let new_cdn_node_params = NodeParams::from("new cdn node params"); + set_caller_value(ctx.provider_id0, CONTRACT_FEE_LIMIT); + ctx.contract.cdn_node_set_params(ctx.cdn_node_key0, new_cdn_node_params.clone())?; + + assert!( + matches!(get_events().pop().unwrap(), Event::CdnNodeParamsSet(ev) if ev == + CdnNodeParamsSet { + cdn_node_key: ctx.cdn_node_key0, + cdn_node_params: new_cdn_node_params.clone() + } + ) + ); + + // Check the changed params. + let cdn_node_info = ctx.contract.cdn_node_get(ctx.cdn_node_key0)?; + assert_eq!(cdn_node_info.cdn_node.cdn_node_params, new_cdn_node_params); +} + + +#[ink::test] +fn node_get_success() { + let ctx = setup_cluster(); + + let v_nodes1_len : u32 = ctx.v_nodes1.len().try_into().unwrap(); + assert_eq!( + ctx.contract.cdn_node_get(ctx.cdn_node_key1), + Ok({ + CdnNodeInfo { + cdn_node_key: ctx.cdn_node_key1, + cdn_node: CdnNode { + provider_id: ctx.provider_id1, + undistributed_payment: 0, + cdn_node_params:ctx.cdn_node_params1, + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + } + }) + ); +} + + +#[ink::test] +fn node_list_success() { + let ctx = setup_cluster(); + + let cdn_node_info = ctx.contract.cdn_node_get(ctx.cdn_node_key1)?; + assert_eq!(ctx.provider_id1, cdn_node_info.cdn_node.provider_id.clone()); + + let v_nodes1_len : u32 = ctx.v_nodes1.len().try_into().unwrap(); + let cdn_node1 = CdnNodeInfo { + cdn_node_key: ctx.cdn_node_key1, + cdn_node: CdnNode { + provider_id: ctx.provider_id1, + undistributed_payment: 0, + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + cdn_node_params: ctx.cdn_node_params1.clone() + }, + }; + + let v_nodes2_len : u32 = ctx.v_nodes2.len().try_into().unwrap(); + let cdn_node2 = CdnNodeInfo { + cdn_node_key: ctx.cdn_node_key2, + cdn_node: CdnNode { + provider_id: ctx.provider_id2, + undistributed_payment: 0, + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + cdn_node_params: ctx.cdn_node_params2.clone() + } + }; + + let count = 3; + + assert_eq!( + ctx.contract.cdn_node_list(1, 100, None), + (vec![cdn_node1.clone(), cdn_node2.clone()], count) + ); + + assert_eq!( + ctx.contract.cdn_node_list(1, 2, None), + (vec![cdn_node1.clone(), cdn_node2.clone()], count) + ); + + assert_eq!( + ctx.contract.cdn_node_list(1, 1, None), + (vec![cdn_node1.clone()], count) + ); + + assert_eq!( + ctx.contract.cdn_node_list(2, 1, None), + (vec![cdn_node2.clone()], count) + ); + + assert_eq!(ctx.contract.cdn_node_list(21, 20, None), (vec![], count)); + + // Filter by owner. + assert_eq!( + ctx.contract.cdn_node_list(1, 100, Some(ctx.provider_id1)), + (vec![cdn_node1.clone()], count) + ); + + assert_eq!( + ctx.contract.cdn_node_list(1, 100, Some(ctx.provider_id2)), + (vec![cdn_node2.clone()], count) + ); + + let not_provider_id= AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + + assert_eq!( + ctx.contract.cdn_node_list(1, 100, Some(not_provider_id)), + (vec![], count) + ); +} diff --git a/bucket/ddc_bucket/tests/test_node.rs b/bucket/ddc_bucket/tests/test_node.rs index 6e37d6b8..a169bd85 100644 --- a/bucket/ddc_bucket/tests/test_node.rs +++ b/bucket/ddc_bucket/tests/test_node.rs @@ -159,8 +159,8 @@ fn node_set_params_success() { ); // Check the changed params. - let status = ctx.contract.node_get(ctx.node_key0)?; - assert_eq!(status.node.node_params, new_node_params); + let node_info = ctx.contract.node_get(ctx.node_key0)?; + assert_eq!(node_info.node.node_params, new_node_params); } diff --git a/bucket/lib.rs b/bucket/lib.rs index 38c76e11..ec0369b1 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -989,7 +989,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `OnlyCdnNodeOwner` error if the caller is not the CDN node owner. + /// * `OnlyCdnNodeProvider` error if the caller is not the CDN node owner. /// * `CdnNodeDoesNotExist` error if the CDN node does not exist. /// * `CdnNodeIsAddedToCluster(ClusterId)` error if the removing CDN node is added to some cluster. #[ink(message)] @@ -1020,7 +1020,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `OnlyCdnNodeOwner` error if the caller is not the CDN node owner. + /// * `OnlyCdnNodeProvider` error if the caller is not the CDN node owner. /// * `CdnNodeDoesNotExist` error if the CDN node does not exist. #[ink(message, payable)] pub fn cdn_node_set_params( @@ -1669,7 +1669,7 @@ pub mod ddc_bucket { ParamsSizeExceedsLimit, OnlyOwner, OnlyNodeProvider, - OnlyCdnNodeOwner, + OnlyCdnNodeProvider, OnlyClusterManager, OnlyTrustedClusterManager, OnlySuperAdmin, From 638fba527793bd5e4e03badca7f88c69777fb48e Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 28 Jun 2023 22:06:41 +0200 Subject: [PATCH 50/89] chore(test): err test scenarios for getting nodes --- bucket/ddc_bucket/tests/test_cdn_node.rs | 23 +++++++++++++--------- bucket/ddc_bucket/tests/test_node.rs | 25 +++++++++++++++--------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/bucket/ddc_bucket/tests/test_cdn_node.rs b/bucket/ddc_bucket/tests/test_cdn_node.rs index 10602494..9beb8562 100644 --- a/bucket/ddc_bucket/tests/test_cdn_node.rs +++ b/bucket/ddc_bucket/tests/test_cdn_node.rs @@ -70,9 +70,7 @@ fn cdn_node_remove_err_if_not_provider() { set_caller(not_provider_id); assert_eq!( - ctx.contract.cdn_node_remove( - ctx.cdn_node_key1, - ), + ctx.contract.cdn_node_remove(ctx.cdn_node_key1), Err(OnlyCdnNodeProvider) ); } @@ -84,9 +82,7 @@ fn cdn_node_remove_err_if_node_in_cluster() { set_caller(ctx.provider_id1); assert_eq!( - ctx.contract.cdn_node_remove( - ctx.cdn_node_key1, - ), + ctx.contract.cdn_node_remove(ctx.cdn_node_key1), Err(CdnNodeIsAddedToCluster(ctx.cluster_id)) ); } @@ -109,9 +105,7 @@ fn cdn_node_remove_success() { ); assert_eq!( - ctx.contract.cdn_node_get( - ctx.cdn_node_key1, - ), + ctx.contract.cdn_node_get(ctx.cdn_node_key1), Err(CdnNodeDoesNotExist) ); } @@ -160,6 +154,17 @@ fn node_set_params_success() { assert_eq!(cdn_node_info.cdn_node.cdn_node_params, new_cdn_node_params); } +#[ink::test] +fn cdn_node_get_err_if_node_does_not_exist() { + let ctx = setup_cluster(); + + let bad_cdn_node_key = AccountId::from([0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, 0x9c, 0x76]); + + assert_eq!( + ctx.contract.cdn_node_get(bad_cdn_node_key), + Err(CdnNodeDoesNotExist) + ); +} #[ink::test] fn node_get_success() { diff --git a/bucket/ddc_bucket/tests/test_node.rs b/bucket/ddc_bucket/tests/test_node.rs index a169bd85..cbef4baf 100644 --- a/bucket/ddc_bucket/tests/test_node.rs +++ b/bucket/ddc_bucket/tests/test_node.rs @@ -73,9 +73,7 @@ fn node_remove_err_if_not_provider() { set_caller(not_provider_id); assert_eq!( - ctx.contract.node_remove( - ctx.node_key1, - ), + ctx.contract.node_remove(ctx.node_key1), Err(OnlyNodeProvider) ); } @@ -87,9 +85,7 @@ fn node_remove_err_if_node_in_cluster() { set_caller(ctx.provider_id1); assert_eq!( - ctx.contract.node_remove( - ctx.node_key1, - ), + ctx.contract.node_remove(ctx.node_key1), Err(NodeIsAddedToCluster(ctx.cluster_id)) ); } @@ -112,9 +108,7 @@ fn node_remove_success() { ); assert_eq!( - ctx.contract.node_get( - ctx.node_key1, - ), + ctx.contract.node_get(ctx.node_key1), Err(NodeDoesNotExist) ); } @@ -164,6 +158,19 @@ fn node_set_params_success() { } +#[ink::test] +fn node_get_err_if_node_does_not_exist() { + let ctx = setup_cluster(); + + let bad_node_key = AccountId::from([0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, 0x9c, 0x76]); + + assert_eq!( + ctx.contract.node_get(bad_node_key), + Err(NodeDoesNotExist) + ); +} + + #[ink::test] fn node_get_success() { let ctx = setup_cluster(); From 549ab1e4d3883578b74b8bc545c02985cfebf4ff Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 28 Jun 2023 23:12:38 +0200 Subject: [PATCH 51/89] chore(test): test scenarios for adding and removing storage nodes in a cluster --- bucket/ddc_bucket/cluster/messages.rs | 4 +- bucket/ddc_bucket/tests/test_cluster.rs | 144 ++++++++++++++++++++++-- 2 files changed, 136 insertions(+), 12 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 83b41f7e..8916741f 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -91,12 +91,12 @@ impl DdcBucket { let mut node = self.nodes.get(node_key)?; let mut cluster = self.clusters.get(cluster_id)?; - node.only_with_cluster(cluster_id)?; - if !cluster.only_manager(caller).is_ok() && !node.only_provider(caller).is_ok() { return Err(OnlyClusterManagerOrNodeOwner); } + + node.only_with_cluster(cluster_id)?; node.unset_cluster(); self.nodes.update(node_key, &node)?; diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 11bf654c..93eaa061 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -2,6 +2,7 @@ use ink_lang as ink; use crate::ddc_bucket::Error::*; use crate::ddc_bucket::*; +use cdn_node::{entity::*}; use super::env_utils::*; use super::setup_utils::*; @@ -17,7 +18,7 @@ fn cluster_create_success() { assert_eq!(ctx.cluster_id, 0, "cluster_id must start at 0"); - // Check cluster nodes + // Check cluster Storage nodes { let node0 = ctx.contract.node_get(ctx.node_key0)?; let v_nodes0 = ctx.contract.get_v_nodes_by_node(ctx.node_key0); @@ -77,6 +78,57 @@ fn cluster_create_success() { ); } + // Check cluster CDN nodes + { + let cdn_node0 = ctx.contract.cdn_node_get(ctx.cdn_node_key0)?; + + assert_eq!( + cdn_node0, + CdnNodeInfo { + cdn_node_key: ctx.cdn_node_key0, + cdn_node: CdnNode { + provider_id: ctx.provider_id0, + undistributed_payment: 0, + cdn_node_params: ctx.cdn_node_params0.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + } + ); + + let cdn_node1 = ctx.contract.cdn_node_get(ctx.cdn_node_key1)?; + + assert_eq!( + cdn_node1, + CdnNodeInfo { + cdn_node_key: ctx.cdn_node_key1, + cdn_node: CdnNode { + provider_id: ctx.provider_id1, + undistributed_payment: 0, + cdn_node_params: ctx.cdn_node_params1.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + } + ); + + let cdn_node2 = ctx.contract.cdn_node_get(ctx.node_key2)?; + + assert_eq!( + cdn_node2, + CdnNodeInfo { + cdn_node_key: ctx.cdn_node_key2, + cdn_node: CdnNode { + provider_id: ctx.provider_id2, + undistributed_payment: 0, + cdn_node_params: ctx.cdn_node_params1.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + } + ); + } + // Check the cluster { let cluster = ctx.contract.cluster_get(ctx.cluster_id)?; @@ -186,7 +238,7 @@ fn cluster_create_success() { #[ink::test] -fn cluster_add_node_err_if_node_in_cluster() { +fn cluster_add_node_err_if_node_is_in_cluster() { let mut ctx = setup_cluster(); let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); @@ -371,7 +423,53 @@ fn cluster_add_node_success() { #[ink::test] -fn cluster_remove_node_success() { +fn cluster_remove_node_err_if_node_is_not_in_cluster() { + let mut ctx = setup_cluster(); + + let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + set_balance(new_provider_id, 1000 * TOKEN); + + let another_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + ctx.contract.node_create( + another_node_key, + NodeParams::from("new_node"), + 1000, + 100 + )?; + + set_caller(ctx.manager_id); + assert_eq!( + ctx.contract.cluster_remove_node( + ctx.cluster_id, + another_node_key, + ), + Err(NodeIsNotAddedToCluster(ctx.cluster_id)) + ); +} + + +#[ink::test] +fn cluster_remove_node_err_if_not_manager_and_not_provider() { + let mut ctx = setup_cluster(); + + let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_manager_id, 1000 * TOKEN); + + set_caller(not_manager_id); + assert_eq!( + ctx.contract.cluster_remove_node( + ctx.cluster_id, + ctx.node_key1, + ), + Err(OnlyClusterManagerOrNodeOwner) + ); +} + + +#[ink::test] +fn cluster_remove_node_success_if_node_provider() { let mut ctx = setup_cluster(); set_caller(ctx.manager_id); @@ -388,24 +486,50 @@ fn cluster_remove_node_success() { }) ); - set_caller(ctx.provider_id1); - ctx.contract.node_remove(ctx.node_key1)?; + let nodes_keys = vec![ + ctx.node_key0, + ctx.node_key2, + ]; + + let cluster_v_nodes = vec![ + ctx.v_nodes0, + ctx.v_nodes2, + ]; + + let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; + cluster_info.cluster_v_nodes.sort(); + assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); + assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); + +} + + +#[ink::test] +fn cluster_remove_node_success_if_cluster_manager() { + let mut ctx = setup_cluster(); + + set_caller(ctx.provider_id2); + ctx.contract.cluster_remove_node( + ctx.cluster_id, + ctx.node_key2 + )?; assert!( - matches!(get_events().pop().unwrap(), Event::NodeRemoved(ev) if ev == - NodeRemoved { - node_key: ctx.node_key1 + matches!(get_events().pop().unwrap(), Event::ClusterNodeRemoved(ev) if ev == + ClusterNodeRemoved { + cluster_id: ctx.cluster_id, + node_key: ctx.node_key2 }) ); let nodes_keys = vec![ ctx.node_key0, - ctx.node_key2, + ctx.node_key1, ]; let cluster_v_nodes = vec![ ctx.v_nodes0, - ctx.v_nodes2, + ctx.v_nodes1, ]; let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; From b183fe02d238a8cd6b8f375032ddbe722d64a21c Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 28 Jun 2023 23:21:38 +0200 Subject: [PATCH 52/89] fix(test): test scenarios for adding and removing storage nodes in a cluster --- bucket/ddc_bucket/tests/test_cluster.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 93eaa061..2481fe85 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -83,6 +83,7 @@ fn cluster_create_success() { let cdn_node0 = ctx.contract.cdn_node_get(ctx.cdn_node_key0)?; assert_eq!( + cdn_node0, CdnNodeInfo { cdn_node_key: ctx.cdn_node_key0, @@ -112,7 +113,7 @@ fn cluster_create_success() { } ); - let cdn_node2 = ctx.contract.cdn_node_get(ctx.node_key2)?; + let cdn_node2 = ctx.contract.cdn_node_get(ctx.cdn_node_key2)?; assert_eq!( cdn_node2, @@ -121,7 +122,7 @@ fn cluster_create_success() { cdn_node: CdnNode { provider_id: ctx.provider_id2, undistributed_payment: 0, - cdn_node_params: ctx.cdn_node_params1.clone(), + cdn_node_params: ctx.cdn_node_params2.clone(), cluster_id: Some(ctx.cluster_id), status_in_cluster: Some(NodeStatusInCluster::ADDING), }, From 757c176b38d1dc67e76bb8250187070a02e4966d Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Wed, 28 Jun 2023 23:56:28 +0200 Subject: [PATCH 53/89] chore(test): test scenarios for adding and removing cdn nodes in a cluster --- bucket/ddc_bucket/cluster/messages.rs | 4 +- bucket/ddc_bucket/tests/test_cluster.rs | 265 +++++++++++++++++++++++- bucket/lib.rs | 8 +- 3 files changed, 266 insertions(+), 11 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 8916741f..aff229c2 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -93,7 +93,7 @@ impl DdcBucket { if !cluster.only_manager(caller).is_ok() && !node.only_provider(caller).is_ok() { - return Err(OnlyClusterManagerOrNodeOwner); + return Err(OnlyClusterManagerOrNodeProvider); } node.only_with_cluster(cluster_id)?; @@ -202,7 +202,7 @@ impl DdcBucket { if !cluster.only_manager(caller).is_ok() && !cdn_node.only_provider(caller).is_ok() { - return Err(OnlyClusterManagerOrCdnNodeOwner); + return Err(OnlyClusterManagerOrCdnNodeProvider); } cdn_node.unset_cluster(); diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 2481fe85..126c5e4b 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -246,9 +246,7 @@ fn cluster_add_node_err_if_node_is_in_cluster() { set_balance(another_manager_id, 1000 * TOKEN); set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - let another_cluster_id = ctx.contract.cluster_create( - ClusterParams::from("{}") - )?; + let another_cluster_id = ctx.contract.cluster_create(ClusterParams::from("{}"))?; assert_eq!( ctx.contract.cluster_add_node( @@ -317,7 +315,7 @@ fn cluster_add_node_err_if_not_cluster_manager() { let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - let new_node_key = ctx.contract.node_create( + ctx.contract.node_create( new_node_key, NodeParams::from("new_node"), 1000, @@ -464,7 +462,7 @@ fn cluster_remove_node_err_if_not_manager_and_not_provider() { ctx.cluster_id, ctx.node_key1, ), - Err(OnlyClusterManagerOrNodeOwner) + Err(OnlyClusterManagerOrNodeProvider) ); } @@ -541,6 +539,263 @@ fn cluster_remove_node_success_if_cluster_manager() { } +#[ink::test] +fn cluster_add_cdn_node_err_if_cdn_node_is_in_cluster() { + let mut ctx = setup_cluster(); + + let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + set_balance(another_manager_id, 1000 * TOKEN); + + set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); + let another_cluster_id = ctx.contract.cluster_create(ClusterParams::from("{}"))?; + + assert_eq!( + ctx.contract.cluster_add_cdn_node( + another_cluster_id, + ctx.cdn_node_key1, + ), + Err(CdnNodeIsAddedToCluster(ctx.cluster_id)) + ); +} + + +#[ink::test] +fn cluster_add_cdn_node_err_if_not_trusted_manager() { + let mut ctx = setup_cluster(); + + let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + set_balance(another_manager_id, 1000 * TOKEN); + + set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); + let another_cluster_id = ctx.contract.cluster_create(ClusterParams::from("{}"))?; + + let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + set_balance(new_provider_id, 1000 * TOKEN); + + let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + let new_node_key = ctx.contract.cdn_node_create( + new_cdn_node_key, + CdnNodeParams::from("new_cdn_node"), + )?; + + set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); + assert_eq!( + ctx.contract.cluster_add_cdn_node( + another_cluster_id, + new_cdn_node_key, + ), + Err(OnlyTrustedClusterManager) + ); +} + + +#[ink::test] +fn cluster_add_cdn_node_err_if_not_cluster_manager() { + let mut ctx = setup_cluster(); + + let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + set_balance(another_manager_id, 1000 * TOKEN); + + set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); + let another_cluster_id = ctx.contract.cluster_create(ClusterParams::from("{}"))?; + + let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + set_balance(new_provider_id, 1000 * TOKEN); + + let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + ctx.contract.cdn_node_create( + new_cdn_node_key, + CdnNodeParams::from("new_cdn_node"), + )?; + + let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_manager_id, 1000 * TOKEN); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + ctx.contract.grant_trusted_manager_permission(not_manager_id)?; + + set_caller_value(not_manager_id, CONTRACT_FEE_LIMIT); + assert_eq!( + ctx.contract.cluster_add_cdn_node( + another_cluster_id, + new_cdn_node_key, + ), + Err(OnlyClusterManager) + ); +} + + +#[ink::test] +fn cluster_add_cdn_node_success() { + let mut ctx = setup_cluster(); + + let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + set_balance(new_provider_id, 1000 * TOKEN); + + let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_cdn_node_params = CdnNodeParams::from("new_cdn_node"); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + ctx.contract.cdn_node_create( + new_cdn_node_key, + new_cdn_node_params.clone(), + )?; + + assert!( + matches!(get_events().pop().unwrap(), Event::CdnNodeCreated(ev) if ev == + CdnNodeCreated { + cdn_node_key: new_cdn_node_key, + provider_id: new_provider_id, + cdn_node_params: new_cdn_node_params, + undistributed_payment: 0 + }) + ); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + ctx.contract.grant_trusted_manager_permission(ctx.manager_id)?; + + assert!( + matches!( + get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == + PermissionGranted { + account_id: ctx.manager_id, + permission: Permission::ClusterManagerTrustedBy(new_provider_id) + } + ) + ); + + set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); + ctx.contract.cluster_add_cdn_node( + ctx.cluster_id, + new_cdn_node_key, + )?; + + assert!( + matches!(get_events().pop().unwrap(), Event::ClusterCdnNodeAdded(ev) if ev == + ClusterCdnNodeAdded { + cluster_id: ctx.cluster_id, + cdn_node_key: new_cdn_node_key + }) + ); + + let cdn_nodes_keys = vec![ + ctx.cdn_node_key0, + ctx.cdn_node_key1, + ctx.cdn_node_key2, + new_cdn_node_key, + ]; + + let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; + assert!(matches!(cluster_info.cluster.cdn_nodes_keys, cdn_nodes_keys)); +} + + +#[ink::test] +fn cluster_remove_cdn_node_err_if_cdn_node_is_not_in_cluster() { + let mut ctx = setup_cluster(); + + let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + set_balance(new_provider_id, 1000 * TOKEN); + + let another_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + + set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); + ctx.contract.cdn_node_create( + another_cdn_node_key, + CdnNodeParams::from("new_cdn_node") + )?; + + set_caller(ctx.manager_id); + assert_eq!( + ctx.contract.cluster_remove_cdn_node( + ctx.cluster_id, + another_cdn_node_key, + ), + Err(CdnNodeIsNotAddedToCluster(ctx.cluster_id)) + ); +} + + +#[ink::test] +fn cluster_remove_cdn_node_err_if_not_manager_and_not_provider() { + let mut ctx = setup_cluster(); + + let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_manager_id, 1000 * TOKEN); + + set_caller(not_manager_id); + assert_eq!( + ctx.contract.cluster_remove_cdn_node( + ctx.cluster_id, + ctx.cdn_node_key1, + ), + Err(OnlyClusterManagerOrCdnNodeProvider) + ); +} + + +#[ink::test] +fn cluster_remove_cdn_node_success_if_cdn_node_provider() { + let mut ctx = setup_cluster(); + + set_caller(ctx.manager_id); + ctx.contract.cluster_remove_cdn_node( + ctx.cluster_id, + ctx.cdn_node_key1 + )?; + + assert!( + matches!(get_events().pop().unwrap(), Event::ClusterCdnNodeRemoved(ev) if ev == + ClusterCdnNodeRemoved { + cluster_id: ctx.cluster_id, + cdn_node_key: ctx.cdn_node_key1 + }) + ); + + let cdn_nodes_keys = vec![ + ctx.cdn_node_key0, + ctx.cdn_node_key2, + ]; + + let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; + assert!(matches!(cluster_info.cluster.cdn_nodes_keys, cdn_nodes_keys)); + +} + + +#[ink::test] +fn cluster_remove_cdn_node_success_if_cluster_manager() { + let mut ctx = setup_cluster(); + + set_caller(ctx.provider_id2); + ctx.contract.cluster_remove_cdn_node( + ctx.cluster_id, + ctx.cdn_node_key2 + )?; + + assert!( + matches!(get_events().pop().unwrap(), Event::ClusterCdnNodeRemoved(ev) if ev == + ClusterCdnNodeRemoved { + cluster_id: ctx.cluster_id, + cdn_node_key: ctx.cdn_node_key2 + }) + ); + + let cdn_nodes_keys = vec![ + ctx.cdn_node_key0, + ctx.cdn_node_key1, + ]; + + let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; + assert!(matches!(cluster_info.cluster.cdn_nodes_keys, cdn_nodes_keys)); + +} + + #[ink::test] fn cluster_set_params_err_if_not_cluster_manager() { let ctx = &mut setup_cluster(); diff --git a/bucket/lib.rs b/bucket/lib.rs index ec0369b1..187d417c 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -475,7 +475,7 @@ pub mod ddc_bucket { /// # Errors /// /// * `ClusterDoesNotExist` error if the cluster does not exist. - /// * `OnlyClusterManagerOrNodeOwner` error if the caller is not the cluster manager or node owner. + /// * `OnlyClusterManagerOrNodeProvider` error if the caller is not the cluster manager or node owner. /// * `NodeDoesNotExist` error if the removing Storage node does not exist. /// * `NodeIsNotAddedToCluster(ClusterId)` error if the removing Storage node is not in this cluster. #[ink(message)] @@ -584,7 +584,7 @@ pub mod ddc_bucket { /// # Errors /// /// * `ClusterDoesNotExist` error if the cluster does not exist. - /// * `OnlyClusterManagerOrCdnNodeOwner` error if the caller is not the cluster manager or node owner. + /// * `OnlyClusterManagerOrCdnNodeProvider` error if the caller is not the cluster manager or node owner. /// * `CdnNodeDoesNotExist` error if the removing CDN node does not exist. /// * `CdnNodeIsNotAddedToCluster(ClusterId)` error if the removing CDN node is not in this cluster. #[ink(message)] @@ -1673,8 +1673,8 @@ pub mod ddc_bucket { OnlyClusterManager, OnlyTrustedClusterManager, OnlySuperAdmin, - OnlyClusterManagerOrNodeOwner, - OnlyClusterManagerOrCdnNodeOwner, + OnlyClusterManagerOrNodeProvider, + OnlyClusterManagerOrCdnNodeProvider, Unauthorized, ClusterDoesNotExist, ClusterIsNotEmpty, From 91ad6c9214393d1ebd92e8429fb1c7cda2289157 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 00:20:52 +0200 Subject: [PATCH 54/89] chore(test): naming for successful scenarios --- bucket/ddc_bucket/cluster/entity.rs | 4 +++- bucket/ddc_bucket/cluster/messages.rs | 3 +-- bucket/ddc_bucket/tests/env_utils.rs | 2 -- bucket/ddc_bucket/tests/test_account.rs | 2 +- bucket/ddc_bucket/tests/test_admin.rs | 14 +++++------ bucket/ddc_bucket/tests/test_bucket.rs | 10 ++++---- bucket/ddc_bucket/tests/test_cdn_node.rs | 10 ++++---- bucket/ddc_bucket/tests/test_cluster.rs | 30 ++++++++++++------------ bucket/ddc_bucket/tests/test_currency.rs | 8 +++---- bucket/ddc_bucket/tests/test_node.rs | 10 ++++---- 10 files changed, 46 insertions(+), 47 deletions(-) diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 399eb0ba..688e8c66 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -50,6 +50,8 @@ pub struct ClusterInfo { } pub const CLUSTER_PARAMS_MAX_LEN: usize = 100_000; +pub const CDN_USD_PER_GB : Balance = 104_857_600; +pub const KB_PER_GB: Balance = 1_000_000; impl Cluster { @@ -67,7 +69,7 @@ impl Cluster { revenues: Cash(0), total_rent: 0, cdn_nodes_keys: Vec::new(), - cdn_usd_per_gb: 104_857_600, // setting initially to 1 cent per GB + cdn_usd_per_gb: CDN_USD_PER_GB, // setting initially to 1 cent per GB cdn_revenues: Cash(0), }; diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index aff229c2..db35587e 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -3,7 +3,7 @@ use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; use crate::ddc_bucket::cash::{Cash, Payable}; -use crate::ddc_bucket::cluster::entity::{ClusterInfo}; +use crate::ddc_bucket::cluster::entity::{ClusterInfo, KB_PER_GB}; use crate::ddc_bucket::bucket::entity::{BucketId}; use crate::ddc_bucket::node::entity::{Node, NodeKey, Resource}; use crate::ddc_bucket::cdn_node::entity::{CdnNode, CdnNodeKey}; @@ -18,7 +18,6 @@ use crate::ddc_bucket::{ use super::entity::{ClusterId, ClusterParams}; -const KB_PER_GB: Balance = 1_000_000; impl DdcBucket { diff --git a/bucket/ddc_bucket/tests/env_utils.rs b/bucket/ddc_bucket/tests/env_utils.rs index b25ae51e..594acfcb 100644 --- a/bucket/ddc_bucket/tests/env_utils.rs +++ b/bucket/ddc_bucket/tests/env_utils.rs @@ -12,8 +12,6 @@ use crate::ddc_bucket::*; pub type Event = ::Type; -pub const KB_PER_GB: Balance = 1_000_000; - /// Recommended contract fee for all operations with reasonable data amounts. pub const CONTRACT_FEE_LIMIT: Balance = 10 * TOKEN; diff --git a/bucket/ddc_bucket/tests/test_account.rs b/bucket/ddc_bucket/tests/test_account.rs index 76aae63b..8a7c8cac 100644 --- a/bucket/ddc_bucket/tests/test_account.rs +++ b/bucket/ddc_bucket/tests/test_account.rs @@ -8,7 +8,7 @@ use crate::ddc_bucket::schedule::{Schedule}; #[ink::test] -fn account_deposit_success() { +fn account_deposit_ok() { let account_id = AccountId::from([0x76, 0x95, 0x7c, 0xa6, 0xbe, 0xf5, 0xa3, 0x6d, 0x67, 0x0d, 0x3a, 0x84, 0xc6, 0x0a, 0xe2, 0xbb, 0xc9, 0x5e, 0xee, 0xde, 0x3a, 0x5f, 0x27, 0x0e, 0x26, 0xe3, 0x43, 0x4c, 0x46, 0xe2, 0x98, 0x10]); set_balance(account_id, 1000 * TOKEN); diff --git a/bucket/ddc_bucket/tests/test_admin.rs b/bucket/ddc_bucket/tests/test_admin.rs index e3f2e28b..f0263fc9 100644 --- a/bucket/ddc_bucket/tests/test_admin.rs +++ b/bucket/ddc_bucket/tests/test_admin.rs @@ -11,7 +11,7 @@ fn not_admin_id() -> AccountId { } #[ink::test] -fn admin_init_works() { +fn admin_init_ok() { let contract = setup_contract(); // The deployer is SuperAdmin. @@ -25,7 +25,7 @@ fn admin_init_works() { #[ink::test] -fn admin_withdraw_works() { +fn admin_withdraw_ok() { let mut contract = setup_contract(); assert_eq!(balance_of(contract_id()), 10); @@ -38,7 +38,7 @@ fn admin_withdraw_works() { #[ink::test] #[should_panic] -fn admin_withdraw_only_admin() { +fn admin_withdraw_err_if_not_admin() { let mut contract = setup_contract(); set_caller(not_admin_id()); @@ -48,7 +48,7 @@ fn admin_withdraw_only_admin() { #[ink::test] -fn admin_grant_works() { +fn admin_grant_ok() { let mut contract = setup_contract(); let permission = Permission::SuperAdmin; @@ -72,7 +72,7 @@ fn admin_grant_works() { #[ink::test] -fn admin_grant_only_admin() { +fn admin_grant_err_if_not_admin() { let mut contract = setup_contract(); set_caller_value(not_admin_id(), CONTRACT_FEE_LIMIT); @@ -89,7 +89,7 @@ fn admin_grant_only_admin() { #[ink::test] #[should_panic] -fn admin_revoke_works() { +fn admin_revoke_ok() { let mut contract = setup_contract(); let permission = Permission::SuperAdmin; @@ -112,7 +112,7 @@ fn admin_revoke_works() { #[ink::test] -fn admin_revoke_only_admin() { +fn admin_revoke_err_if_not_admin() { let mut contract = setup_contract(); set_caller_value(not_admin_id(), CONTRACT_FEE_LIMIT); diff --git a/bucket/ddc_bucket/tests/test_bucket.rs b/bucket/ddc_bucket/tests/test_bucket.rs index 010c7df0..697daffe 100644 --- a/bucket/ddc_bucket/tests/test_bucket.rs +++ b/bucket/ddc_bucket/tests/test_bucket.rs @@ -82,7 +82,7 @@ fn do_bucket_pays_cluster( #[ink::test] -fn bucket_pays_cluster_success() { +fn bucket_pays_cluster_ok() { let ctx = &mut setup_cluster(); let test_bucket = &setup_bucket(ctx); do_bucket_pays_cluster(ctx, test_bucket, 1).unwrap(); @@ -90,7 +90,7 @@ fn bucket_pays_cluster_success() { #[ink::test] -fn bucket_pays_cluster_at_new_rate_success() { +fn bucket_pays_cluster_at_new_rate_ok() { let ctx = &mut setup_cluster(); let test_bucket = &setup_bucket(ctx); @@ -110,7 +110,7 @@ fn bucket_pays_cluster_at_new_rate_success() { #[ink::test] -fn bucket_create_success() { +fn bucket_create_ok() { let ctx = &mut setup_cluster(); let test_bucket = &setup_bucket(ctx); @@ -167,7 +167,7 @@ fn bucket_create_success() { #[ink::test] -fn bucket_change_params_success() { +fn bucket_change_params_ok() { let ctx = &mut setup_cluster(); let test_bucket = &setup_bucket(ctx); @@ -196,7 +196,7 @@ fn bucket_change_params_only_owner() { #[ink::test] -fn bucket_list_success() { +fn bucket_list_ok() { let mut ddc_bucket = setup_contract(); let owner_id1 = AccountId::from([0xd8, 0x69, 0x19, 0x54, 0xea, 0xdc, 0x9a, 0xc0, 0x3d, 0x37, 0x56, 0x9f, 0x2a, 0xe8, 0xdf, 0x59, 0x34, 0x3f, 0x32, 0x65, 0xba, 0xd4, 0x16, 0xac, 0x07, 0xdf, 0x06, 0xeb, 0x4d, 0xbc, 0x6a, 0x66]); diff --git a/bucket/ddc_bucket/tests/test_cdn_node.rs b/bucket/ddc_bucket/tests/test_cdn_node.rs index 9beb8562..668fe757 100644 --- a/bucket/ddc_bucket/tests/test_cdn_node.rs +++ b/bucket/ddc_bucket/tests/test_cdn_node.rs @@ -22,7 +22,7 @@ fn cdn_node_create_err_if_node_exists() { #[ink::test] -fn cdn_node_create_success() { +fn cdn_node_create_ok() { let mut ctx = setup_cluster(); let new_provider_id = AccountId::from([0x76, 0x30, 0xc6, 0x96, 0x6f, 0xd3, 0x26, 0xba, 0x1a, 0xa0, 0x6f, 0xd8, 0x7f, 0x7b, 0xf2, 0xef, 0x14, 0x11, 0xf0, 0x0d, 0x00, 0xa9, 0xe7, 0x11, 0xdf, 0xd1, 0x65, 0x14, 0x5d, 0x01, 0xdb, 0x59]); @@ -89,7 +89,7 @@ fn cdn_node_remove_err_if_node_in_cluster() { #[ink::test] -fn cdn_node_remove_success() { +fn cdn_node_remove_ok() { let mut ctx = setup_cluster(); set_caller(ctx.provider_id1); @@ -132,7 +132,7 @@ fn cdn_node_set_params_err_if_not_provider() { #[ink::test] -fn node_set_params_success() { +fn node_set_params_ok() { let mut ctx = setup_cluster(); // Change params. @@ -167,7 +167,7 @@ fn cdn_node_get_err_if_node_does_not_exist() { } #[ink::test] -fn node_get_success() { +fn node_get_ok() { let ctx = setup_cluster(); let v_nodes1_len : u32 = ctx.v_nodes1.len().try_into().unwrap(); @@ -190,7 +190,7 @@ fn node_get_success() { #[ink::test] -fn node_list_success() { +fn node_list_ok() { let ctx = setup_cluster(); let cdn_node_info = ctx.contract.cdn_node_get(ctx.cdn_node_key1)?; diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 126c5e4b..ffd413e3 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -8,7 +8,7 @@ use super::setup_utils::*; #[ink::test] -fn cluster_create_success() { +fn cluster_create_ok() { let ctx = setup_cluster(); let providers_ids = &[ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; let node_keys = &[ctx.node_key0, ctx.node_key1, ctx.node_key2]; @@ -147,7 +147,7 @@ fn cluster_create_success() { revenues: Cash(0), total_rent: ctx.rent_per_month * ctx.cluster_v_nodes.len() as Balance, cdn_nodes_keys: ctx.cdn_nodes_keys, - cdn_usd_per_gb: 104_857_600, + cdn_usd_per_gb: CDN_USD_PER_GB, cdn_revenues: Cash(0), }, cluster_v_nodes @@ -342,7 +342,7 @@ fn cluster_add_node_err_if_not_cluster_manager() { #[ink::test] -fn cluster_add_node_success() { +fn cluster_add_node_ok() { let mut ctx = setup_cluster(); let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); @@ -468,7 +468,7 @@ fn cluster_remove_node_err_if_not_manager_and_not_provider() { #[ink::test] -fn cluster_remove_node_success_if_node_provider() { +fn cluster_remove_node_ok_if_node_provider() { let mut ctx = setup_cluster(); set_caller(ctx.manager_id); @@ -504,7 +504,7 @@ fn cluster_remove_node_success_if_node_provider() { #[ink::test] -fn cluster_remove_node_success_if_cluster_manager() { +fn cluster_remove_node_ok_if_cluster_manager() { let mut ctx = setup_cluster(); set_caller(ctx.provider_id2); @@ -630,7 +630,7 @@ fn cluster_add_cdn_node_err_if_not_cluster_manager() { #[ink::test] -fn cluster_add_cdn_node_success() { +fn cluster_add_cdn_node_ok() { let mut ctx = setup_cluster(); let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); @@ -739,7 +739,7 @@ fn cluster_remove_cdn_node_err_if_not_manager_and_not_provider() { #[ink::test] -fn cluster_remove_cdn_node_success_if_cdn_node_provider() { +fn cluster_remove_cdn_node_ok_if_cdn_node_provider() { let mut ctx = setup_cluster(); set_caller(ctx.manager_id); @@ -768,7 +768,7 @@ fn cluster_remove_cdn_node_success_if_cdn_node_provider() { #[ink::test] -fn cluster_remove_cdn_node_success_if_cluster_manager() { +fn cluster_remove_cdn_node_ok_if_cluster_manager() { let mut ctx = setup_cluster(); set_caller(ctx.provider_id2); @@ -817,7 +817,7 @@ fn cluster_set_params_err_if_not_cluster_manager() { #[ink::test] -fn cluster_set_params_success() { +fn cluster_set_params_ok() { let mut ctx = setup_cluster(); // Change params. @@ -869,7 +869,7 @@ fn cluster_replace_node_err_if_node_does_not_exist() { #[ink::test] -fn cluster_replace_node_success() { +fn cluster_replace_node_ok() { let mut ctx = setup_cluster(); set_caller(ctx.manager_id); @@ -929,7 +929,7 @@ fn cluster_replace_node_success() { #[ink::test] -fn cluster_reserve_resource_success() { +fn cluster_reserve_resource_ok() { let mut ctx = setup_cluster(); set_caller(ctx.manager_id); @@ -966,7 +966,7 @@ fn cluster_reserve_resource_success() { #[ink::test] -fn cluster_distribute_revenue_success() { +fn cluster_distribute_revenue_ok() { let ctx = &mut setup_cluster(); let test_bucket = &setup_bucket(ctx); // Go to the future when some revenues are due. @@ -1073,7 +1073,7 @@ fn cluster_distribute_revenue_success() { #[ink::test] -fn cluster_distribute_cdn_revenue_success() { +fn cluster_distribute_cdn_revenue_ok() { // todo: this test scenario must be revised as it does pure printing without any assertion println!("Creating new cdn cluster"); @@ -1152,8 +1152,8 @@ fn cluster_distribute_cdn_revenue_success() { println!("{:?}", cdn_node0); println!("{:?}", cdn_node1); - let cdn_cluster_list = ctx.contract.cluster_list(0, 10, None); - println!("{:?}", cdn_cluster_list); + let cluster_list_1 = ctx.contract.cluster_list(0, 10, None); + println!("{:?}", cluster_list_1); let account0_after_distributing = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); println!("{:?}", account0_after_distributing); diff --git a/bucket/ddc_bucket/tests/test_currency.rs b/bucket/ddc_bucket/tests/test_currency.rs index 9cd99e3f..9bb32b27 100644 --- a/bucket/ddc_bucket/tests/test_currency.rs +++ b/bucket/ddc_bucket/tests/test_currency.rs @@ -6,7 +6,7 @@ use super::setup_utils::*; #[ink::test] -fn currency_conversion_init_success() { +fn currency_conversion_init_ok() { let contract = setup_contract(); let usd_amount = contract.account_get_usd_per_cere(); println!("{}", usd_amount); @@ -19,7 +19,7 @@ fn currency_conversion_init_success() { #[ink::test] -fn currency_conversion_set_rate_success() { +fn currency_conversion_set_rate_ok() { let mut contract = setup_contract(); let usd_per_cere = TOKEN / 10; println!("{}", usd_per_cere); @@ -37,7 +37,7 @@ fn currency_conversion_set_rate_success() { #[ink::test] #[should_panic] -fn currency_conversion_set_rate_only_admin() { +fn currency_conversion_set_rate_err_if_not_admin() { let mut contract = setup_contract(); let not_admin = get_accounts().bob; @@ -47,7 +47,7 @@ fn currency_conversion_set_rate_only_admin() { #[ink::test] -fn converter_success() { +fn converter_ok() { // todo: this test scenario must be revised as it does pure printing without any assertion println!("Creating new cdn cluster"); diff --git a/bucket/ddc_bucket/tests/test_node.rs b/bucket/ddc_bucket/tests/test_node.rs index cbef4baf..5447e2a0 100644 --- a/bucket/ddc_bucket/tests/test_node.rs +++ b/bucket/ddc_bucket/tests/test_node.rs @@ -22,7 +22,7 @@ fn node_create_err_if_node_exists() { #[ink::test] -fn node_create_success() { +fn node_create_ok() { let mut ctx = setup_cluster(); let new_provider_id = AccountId::from([0x76, 0x30, 0xc6, 0x96, 0x6f, 0xd3, 0x26, 0xba, 0x1a, 0xa0, 0x6f, 0xd8, 0x7f, 0x7b, 0xf2, 0xef, 0x14, 0x11, 0xf0, 0x0d, 0x00, 0xa9, 0xe7, 0x11, 0xdf, 0xd1, 0x65, 0x14, 0x5d, 0x01, 0xdb, 0x59]); @@ -92,7 +92,7 @@ fn node_remove_err_if_node_in_cluster() { #[ink::test] -fn node_remove_success() { +fn node_remove_ok() { let mut ctx = setup_cluster(); set_caller(ctx.provider_id1); @@ -135,7 +135,7 @@ fn node_set_params_err_if_not_provider() { #[ink::test] -fn node_set_params_success() { +fn node_set_params_ok() { let mut ctx = setup_cluster(); // Change params. @@ -172,7 +172,7 @@ fn node_get_err_if_node_does_not_exist() { #[ink::test] -fn node_get_success() { +fn node_get_ok() { let ctx = setup_cluster(); let v_nodes1_len : u32 = ctx.v_nodes1.len().try_into().unwrap(); @@ -197,7 +197,7 @@ fn node_get_success() { #[ink::test] -fn node_list_success() { +fn node_list_ok() { let ctx = setup_cluster(); let node_info = ctx.contract.node_get(ctx.node_key1)?; From 1263e5d6ee1ae43c734761e83b0d8956f5c52475 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 00:45:02 +0200 Subject: [PATCH 55/89] chore(test): test scenarios for removing a cluster --- bucket/ddc_bucket/cluster/messages.rs | 4 +- bucket/ddc_bucket/tests/test_cluster.rs | 91 +++++++++++++++++++++++-- 2 files changed, 87 insertions(+), 8 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index db35587e..cd23198b 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -197,12 +197,12 @@ impl DdcBucket { let mut cdn_node: CdnNode = self.cdn_nodes.get(cdn_node_key)?; let mut cluster = self.clusters.get(cluster_id)?; - cdn_node.only_with_cluster(cluster_id)?; - if !cluster.only_manager(caller).is_ok() && !cdn_node.only_provider(caller).is_ok() { return Err(OnlyClusterManagerOrCdnNodeProvider); } + + cdn_node.only_with_cluster(cluster_id)?; cdn_node.unset_cluster(); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index ffd413e3..53e24756 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -857,12 +857,11 @@ fn cluster_replace_node_err_if_node_does_not_exist() { let bad_node_key = AccountId::from([0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, 0x9c, 0x76]); set_caller(ctx.manager_id); assert_eq!( - ctx.contract - .cluster_replace_node( - ctx.cluster_id, - vec![1, 2, 3], - bad_node_key - ), + ctx.contract.cluster_replace_node( + ctx.cluster_id, + vec![1, 2, 3], + bad_node_key + ), Err(NodeDoesNotExist) ); } @@ -1072,6 +1071,86 @@ fn cluster_distribute_revenue_ok() { } +#[ink::test] +fn cluster_remove_err_if_not_cluster_manager() { + let mut ctx = setup_cluster(); + + let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_manager_id, 1000 * TOKEN); + + set_caller(not_manager_id); + assert_eq!( + ctx.contract.cluster_remove(ctx.cluster_id), + Err(OnlyClusterManager) + ); +} + + +#[ink::test] +fn cluster_remove_err_if_cluster_is_not_empty() { + let mut ctx = setup_cluster(); + + set_caller(ctx.manager_id); + assert_eq!( + ctx.contract.cluster_remove(ctx.cluster_id), + Err(ClusterIsNotEmpty) + ); +} + + +#[ink::test] +fn cluster_remove_ok() { + let mut ctx = setup_cluster(); + + set_caller(ctx.manager_id); + + ctx.contract.cluster_remove_node( + ctx.cluster_id, + ctx.node_key0, + )?; + + ctx.contract.cluster_remove_node( + ctx.cluster_id, + ctx.node_key1, + )?; + + ctx.contract.cluster_remove_node( + ctx.cluster_id, + ctx.node_key2, + )?; + + ctx.contract.cluster_remove_cdn_node( + ctx.cluster_id, + ctx.cdn_node_key0, + )?; + + ctx.contract.cluster_remove_cdn_node( + ctx.cluster_id, + ctx.cdn_node_key1, + )?; + + ctx.contract.cluster_remove_cdn_node( + ctx.cluster_id, + ctx.cdn_node_key2, + )?; + + ctx.contract.cluster_remove(ctx.cluster_id)?; + + assert!( + matches!(get_events().pop().unwrap(), Event::ClusterRemoved(ev) if ev == + ClusterRemoved { + cluster_id: ctx.cluster_id, + }) + ); + + assert_eq!( + ctx.contract.cluster_get(ctx.cluster_id), + Err(ClusterDoesNotExist) + ); + +} + + #[ink::test] fn cluster_distribute_cdn_revenue_ok() { // todo: this test scenario must be revised as it does pure printing without any assertion From 4cefb57500d75ea27c0e2c574f14975b97b95013 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 01:05:27 +0200 Subject: [PATCH 56/89] chore(test): test scenarios for setting node and cdn node status in cluster --- bucket/ddc_bucket/tests/test_cluster.rs | 82 ++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 3 deletions(-) diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 53e24756..a3345213 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -284,7 +284,7 @@ fn cluster_add_node_err_if_not_trusted_manager() { 100 )?; - let new_v_nodes: Vec = vec![10, 11, 12]; + let new_v_nodes: Vec = vec![10, 11, 12]; set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); assert_eq!( ctx.contract.cluster_add_node( @@ -328,7 +328,7 @@ fn cluster_add_node_err_if_not_cluster_manager() { set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); ctx.contract.grant_trusted_manager_permission(not_manager_id)?; - let new_v_nodes: Vec = vec![10, 11, 12]; + let new_v_nodes: Vec = vec![10, 11, 12]; set_caller_value(not_manager_id, CONTRACT_FEE_LIMIT); assert_eq!( ctx.contract.cluster_add_node( @@ -384,7 +384,7 @@ fn cluster_add_node_ok() { ) ); - let new_v_nodes: Vec = vec![10, 11, 12]; + let new_v_nodes: Vec = vec![10, 11, 12]; set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); ctx.contract.cluster_add_node( ctx.cluster_id, @@ -1151,6 +1151,82 @@ fn cluster_remove_ok() { } +#[ink::test] +fn cluster_set_node_status_err_if_not_cluster_manager() { + let mut ctx = setup_cluster(); + + let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_manager_id, 1000 * TOKEN); + + set_caller(not_manager_id); + assert_eq!( + ctx.contract.cluster_set_node_status( + ctx.cluster_id, + ctx.node_key0, + NodeStatusInCluster::ACTIVE + ), + Err(OnlyClusterManager) + ); +} + + +#[ink::test] +fn cluster_set_node_status_ok() { + let mut ctx = setup_cluster(); + + set_caller(ctx.manager_id); + ctx.contract.cluster_set_node_status( + ctx.cluster_id, + ctx.node_key0, + NodeStatusInCluster::ACTIVE + )?; + + let node_info = ctx.contract.node_get(ctx.node_key0)?; + assert_eq!( + node_info.node.status_in_cluster, + Some(NodeStatusInCluster::ACTIVE) + ); +} + + +#[ink::test] +fn cluster_set_cdn_node_status_err_if_not_cluster_manager() { + let mut ctx = setup_cluster(); + + let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_balance(not_manager_id, 1000 * TOKEN); + + set_caller(not_manager_id); + assert_eq!( + ctx.contract.cluster_set_cdn_node_status( + ctx.cluster_id, + ctx.cdn_node_key0, + NodeStatusInCluster::ACTIVE + ), + Err(OnlyClusterManager) + ); +} + + +#[ink::test] +fn cluster_set_cdn_node_status_ok() { + let mut ctx = setup_cluster(); + + set_caller(ctx.manager_id); + ctx.contract.cluster_set_cdn_node_status( + ctx.cluster_id, + ctx.cdn_node_key0, + NodeStatusInCluster::ACTIVE + )?; + + let cdn_node_info = ctx.contract.cdn_node_get(ctx.cdn_node_key0)?; + assert_eq!( + cdn_node_info.cdn_node.status_in_cluster, + Some(NodeStatusInCluster::ACTIVE) + ); +} + + #[ink::test] fn cluster_distribute_cdn_revenue_ok() { // todo: this test scenario must be revised as it does pure printing without any assertion From 34b8425a8b9e76a9f52a305950424e4c170f7b2f Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 01:31:15 +0200 Subject: [PATCH 57/89] chore(test): additional asserts for adding and removing nodes in cluster --- bucket/ddc_bucket/tests/test_cluster.rs | 91 +++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 4 deletions(-) diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index a3345213..68296c6d 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -367,7 +367,7 @@ fn cluster_add_node_ok() { node_key: new_node_key, provider_id: new_provider_id, rent_per_month: new_node_rent_per_month, - node_params: new_node_params + node_params: new_node_params.clone(), }) ); @@ -411,13 +411,28 @@ fn cluster_add_node_ok() { ctx.v_nodes0, ctx.v_nodes1, ctx.v_nodes2, - new_v_nodes + new_v_nodes.clone() ]; let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; cluster_info.cluster_v_nodes.sort(); assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); + + let node_info = ctx.contract.node_get(new_node_key)?; + let expected_node_info = NodeInfo { + node_key: new_node_key, + node: Node { + provider_id: new_provider_id, + rent_per_month: new_node_rent_per_month, + free_resource: new_node_capacity, + node_params: new_node_params, + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING) + }, + v_nodes: new_v_nodes + }; + assert!(matches!(node_info, expected_node_info)); } @@ -499,6 +514,21 @@ fn cluster_remove_node_ok_if_node_provider() { cluster_info.cluster_v_nodes.sort(); assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); + + let node_info = ctx.contract.node_get(ctx.node_key1)?; + let expected_node_info = NodeInfo { + node_key: ctx.node_key1, + node: Node { + provider_id: ctx.provider_id1, + rent_per_month: ctx.rent_per_month, + free_resource: ctx.capacity - ctx.reserved_resource * 3, + node_params: ctx.node_params1, + cluster_id: None, + status_in_cluster: None + }, + v_nodes: Vec::new() + }; + assert!(matches!(node_info, expected_node_info)); } @@ -535,6 +565,21 @@ fn cluster_remove_node_ok_if_cluster_manager() { cluster_info.cluster_v_nodes.sort(); assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); + + let node_info = ctx.contract.node_get(ctx.node_key2)?; + let expected_node_info = NodeInfo { + node_key: ctx.node_key2, + node: Node { + provider_id: ctx.provider_id2, + rent_per_month: ctx.rent_per_month, + free_resource: ctx.capacity - ctx.reserved_resource * 3, + node_params: ctx.node_params2, + cluster_id: None, + status_in_cluster: None + }, + v_nodes: Vec::new() + }; + assert!(matches!(node_info, expected_node_info)); } @@ -650,7 +695,7 @@ fn cluster_add_cdn_node_ok() { CdnNodeCreated { cdn_node_key: new_cdn_node_key, provider_id: new_provider_id, - cdn_node_params: new_cdn_node_params, + cdn_node_params: new_cdn_node_params.clone(), undistributed_payment: 0 }) ); @@ -691,6 +736,19 @@ fn cluster_add_cdn_node_ok() { let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; assert!(matches!(cluster_info.cluster.cdn_nodes_keys, cdn_nodes_keys)); + + let cdn_node_info = ctx.contract.cdn_node_get(new_cdn_node_key)?; + let expected_cdn_node_info = CdnNodeInfo { + cdn_node_key: new_cdn_node_key, + cdn_node: CdnNode { + provider_id: new_provider_id, + undistributed_payment: 0, + cdn_node_params: new_cdn_node_params, + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING) + }, + }; + assert!(matches!(cdn_node_info, expected_cdn_node_info)); } @@ -763,6 +821,19 @@ fn cluster_remove_cdn_node_ok_if_cdn_node_provider() { let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; assert!(matches!(cluster_info.cluster.cdn_nodes_keys, cdn_nodes_keys)); + + let cdn_node_info = ctx.contract.cdn_node_get(ctx.cdn_node_key1)?; + let expected_cdn_node_info = CdnNodeInfo { + cdn_node_key: ctx.cdn_node_key1, + cdn_node: CdnNode { + provider_id: ctx.provider_id1, + undistributed_payment: 0, + cdn_node_params: ctx.cdn_node_params1, + cluster_id: None, + status_in_cluster: None + }, + }; + assert!(matches!(cdn_node_info, expected_cdn_node_info)); } @@ -792,7 +863,19 @@ fn cluster_remove_cdn_node_ok_if_cluster_manager() { let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; assert!(matches!(cluster_info.cluster.cdn_nodes_keys, cdn_nodes_keys)); - + + let cdn_node_info = ctx.contract.cdn_node_get(ctx.cdn_node_key2)?; + let expected_cdn_node_info = CdnNodeInfo { + cdn_node_key: ctx.cdn_node_key2, + cdn_node: CdnNode { + provider_id: ctx.provider_id2, + undistributed_payment: 0, + cdn_node_params: ctx.cdn_node_params2, + cluster_id: None, + status_in_cluster: None + }, + }; + assert!(matches!(cdn_node_info, expected_cdn_node_info)); } From 6b190e08e0a646ab05bbcf9e84830ab483359764 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 02:04:16 +0200 Subject: [PATCH 58/89] chore(test): test scenario for cluster listing --- bucket/ddc_bucket/cluster/messages.rs | 2 +- bucket/ddc_bucket/tests/test_cluster.rs | 94 +++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index cd23198b..ccba19e2 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -413,7 +413,7 @@ impl DdcBucket { clusters.push(cluster_info); } - (clusters, self.clusters.next_cluster_id - 1) + (clusters, self.clusters.next_cluster_id) } diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 68296c6d..3f7f4cd4 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -1309,6 +1309,100 @@ fn cluster_set_cdn_node_status_ok() { ); } +#[ink::test] +fn cluster_list_ok() { + let mut ctx = setup_cluster(); + + let mut cluster_v_nodes1 = Vec::::new(); + cluster_v_nodes1.extend(ctx.v_nodes0.clone()); + cluster_v_nodes1.extend(ctx.v_nodes1.clone()); + cluster_v_nodes1.extend(ctx.v_nodes2.clone()); + + let cluster1 = ClusterInfo { + cluster_id: ctx.cluster_id, + cluster: Cluster { + manager_id: ctx.manager_id, + nodes_keys: ctx.nodes_keys, + resource_per_v_node: ctx.reserved_resource, + resource_used: 0, + cluster_params: ctx.cluster_params.clone(), + revenues: Cash(0), + total_rent: ctx.rent_per_month * ctx.cluster_v_nodes.len() as Balance, + cdn_nodes_keys: ctx.cdn_nodes_keys, + cdn_usd_per_gb: CDN_USD_PER_GB, + cdn_revenues: Cash(0), + }, + cluster_v_nodes: cluster_v_nodes1 + }; + + let cluster_params2 = ClusterParams::from("{}"); + let manager_id2 = AccountId::from([0x82, 0x61, 0x19, 0xd5, 0xcf, 0x47, 0xdc, 0xb9, 0xc6, 0xff, 0x1a, 0x3e, 0x46, 0x03, 0x6d, 0xad, 0x1f, 0xea, 0x66, 0x18, 0x96, 0x2e, 0x4a, 0x5e, 0x89, 0xe0, 0x96, 0x74, 0xcf, 0x80, 0xf1, 0x30]); + set_balance(manager_id2, 1000 * TOKEN); + + set_caller(manager_id2); + let cluster_id2 = ctx.contract.cluster_create(cluster_params2.clone())?; + + let cluster2 = ClusterInfo { + cluster_id: cluster_id2, + cluster: Cluster { + manager_id: manager_id2, + nodes_keys: Vec::new(), + resource_per_v_node: 0, + resource_used: 0, + cluster_params: cluster_params2, + revenues: Cash(0), + total_rent: 0, + cdn_nodes_keys: Vec::new(), + cdn_usd_per_gb: CDN_USD_PER_GB, + cdn_revenues: Cash(0), + }, + cluster_v_nodes: Vec::new() + }; + + let count = 2; + + + assert_eq!( + ctx.contract.cluster_list(0, 100, None), + (vec![cluster1.clone(), cluster2.clone()], count) + ); + + assert_eq!( + ctx.contract.cluster_list(0, 2, None), + (vec![cluster1.clone(), cluster2.clone()], count) + ); + + assert_eq!( + ctx.contract.cluster_list(0, 1, None), + (vec![cluster1.clone()], count) + ); + + assert_eq!( + ctx.contract.cluster_list(1, 1, None), + (vec![cluster2.clone()], count) + ); + + + assert_eq!(ctx.contract.cluster_list(21, 20, None), (vec![], count)); + + // Filter by manager. + assert_eq!( + ctx.contract.cluster_list(0, 100, Some(ctx.manager_id)), + (vec![cluster1.clone()], count) + ); + + assert_eq!( + ctx.contract.cluster_list(0, 100, Some(manager_id2)), + (vec![cluster2.clone()], count) + ); + + let not_manager_id= AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + assert_eq!( + ctx.contract.cluster_list(0, 100, Some(not_manager_id)), + (vec![], count) + ); +} + #[ink::test] fn cluster_distribute_cdn_revenue_ok() { From 03430d0d37524f3e4d762733c2f2445849ee81f0 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 02:11:06 +0200 Subject: [PATCH 59/89] chore(test): test scenario for getting cluster --- bucket/ddc_bucket/tests/test_cluster.rs | 46 +++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 3f7f4cd4..af565261 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -1309,6 +1309,52 @@ fn cluster_set_cdn_node_status_ok() { ); } + +#[ink::test] +fn cluster_get_err_if_cluster_does_not_exist() { + let ctx = setup_cluster(); + + let bad_cluster_id = 10000; + assert_eq!( + ctx.contract.cluster_get(bad_cluster_id), + Err(ClusterDoesNotExist) + ); +} + + +#[ink::test] +fn cluster_get_ok() { + let ctx = setup_cluster(); + + let mut cluster_v_nodes1 = Vec::::new(); + cluster_v_nodes1.extend(ctx.v_nodes0.clone()); + cluster_v_nodes1.extend(ctx.v_nodes1.clone()); + cluster_v_nodes1.extend(ctx.v_nodes2.clone()); + + assert_eq!( + ctx.contract.cluster_get(ctx.cluster_id), + Ok({ + ClusterInfo { + cluster_id: ctx.cluster_id, + cluster: Cluster { + manager_id: ctx.manager_id, + nodes_keys: ctx.nodes_keys, + resource_per_v_node: ctx.reserved_resource, + resource_used: 0, + cluster_params: ctx.cluster_params.clone(), + revenues: Cash(0), + total_rent: ctx.rent_per_month * ctx.cluster_v_nodes.len() as Balance, + cdn_nodes_keys: ctx.cdn_nodes_keys, + cdn_usd_per_gb: CDN_USD_PER_GB, + cdn_revenues: Cash(0), + }, + cluster_v_nodes: cluster_v_nodes1 + } + }) + ); +} + + #[ink::test] fn cluster_list_ok() { let mut ctx = setup_cluster(); From 7111bb39d222ee0a0ad34926a9bfc1ee031e70fe Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 02:30:08 +0200 Subject: [PATCH 60/89] chore(test): test scenario for granting and revoking trusted manager permission --- bucket/ddc_bucket/tests/test_cluster.rs | 43 +++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index af565261..5807a868 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -1450,6 +1450,49 @@ fn cluster_list_ok() { } +#[ink::test] +fn grant_and_revoke_trusted_manager_permission_ok() { + let mut contract = setup_contract(); + + let grantor = AccountId::from([0x92, 0xad, 0x47, 0xdf, 0xb9, 0x6b, 0x2b, 0x4a, 0xd5, 0xb0, 0xe3, 0x6d, 0x56, 0x33, 0x27, 0xfd, 0xcf, 0x9d, 0xee, 0x06, 0xf4, 0x0d, 0x41, 0x48, 0xe1, 0x6a, 0x5c, 0xaa, 0x6c, 0x0d, 0x17, 0x4b]); + set_balance(grantor, 1000 * TOKEN); + + let grantee = AccountId::from([0x1a, 0xa6, 0x69, 0xb4, 0x23, 0xe4, 0x8b, 0xbd, 0xc4, 0x65, 0xe3, 0xee, 0x17, 0xfd, 0x5b, 0x6d, 0x6f, 0xae, 0x6f, 0xf1, 0x40, 0x52, 0x03, 0x65, 0x02, 0xe4, 0x50, 0xb5, 0x0b, 0x34, 0xe2, 0x7a]); + set_balance(grantee, 1000 * TOKEN); + + let permission = Permission::ClusterManagerTrustedBy(grantor); + + assert!(!contract.has_permission(grantee, permission)); + + set_caller(grantor); + contract.grant_trusted_manager_permission(grantee)?; + + assert!(contract.has_permission(grantee, permission)); + + assert!( + matches!(get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == + PermissionGranted { + account_id: grantee, + permission + }) + ); + + set_caller(grantor); + contract.revoke_trusted_manager_permission(grantee)?; + + assert!(!contract.has_permission(grantee, permission)); + + assert!( + matches!(get_events().pop().unwrap(), Event::PermissionRevoked(ev) if ev == + PermissionRevoked { + account_id: grantee, + permission + }) + ); + +} + + #[ink::test] fn cluster_distribute_cdn_revenue_ok() { // todo: this test scenario must be revised as it does pure printing without any assertion From 329d8102ca94aea452bb65034624366068ed87d5 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 03:04:21 +0200 Subject: [PATCH 61/89] chore(test): test scenarios for transferring storage and cdn node ownership --- bucket/ddc_bucket/tests/env_utils.rs | 8 - bucket/ddc_bucket/tests/setup_utils.rs | 8 +- bucket/ddc_bucket/tests/test_admin.rs | 211 ++++++++++++++++++++++++- 3 files changed, 217 insertions(+), 10 deletions(-) diff --git a/bucket/ddc_bucket/tests/env_utils.rs b/bucket/ddc_bucket/tests/env_utils.rs index 594acfcb..7402cdbf 100644 --- a/bucket/ddc_bucket/tests/env_utils.rs +++ b/bucket/ddc_bucket/tests/env_utils.rs @@ -54,14 +54,6 @@ pub fn get_events() -> Vec { raw_events.iter().map(decode_event).collect() } -pub fn admin_id() -> AccountId { - get_accounts().alice -} - -pub fn contract_id() -> AccountId { - AccountId::from([0x09; 32]) -} - pub fn print_events(events: &[Event]) { for ev in events.iter() { match ev { diff --git a/bucket/ddc_bucket/tests/setup_utils.rs b/bucket/ddc_bucket/tests/setup_utils.rs index 4ab88d28..67350277 100644 --- a/bucket/ddc_bucket/tests/setup_utils.rs +++ b/bucket/ddc_bucket/tests/setup_utils.rs @@ -2,6 +2,13 @@ use crate::ddc_bucket::*; use super::env_utils::*; +pub fn admin_id() -> AccountId { + get_accounts().alice +} + +pub fn contract_id() -> AccountId { + AccountId::from([0x09; 32]) +} pub fn setup_contract() -> DdcBucket { set_caller(admin_id()); @@ -11,7 +18,6 @@ pub fn setup_contract() -> DdcBucket { contract } - pub struct TestCluster { pub contract: DdcBucket, diff --git a/bucket/ddc_bucket/tests/test_admin.rs b/bucket/ddc_bucket/tests/test_admin.rs index f0263fc9..21581822 100644 --- a/bucket/ddc_bucket/tests/test_admin.rs +++ b/bucket/ddc_bucket/tests/test_admin.rs @@ -124,4 +124,213 @@ fn admin_revoke_err_if_not_admin() { ), Err(OnlySuperAdmin) ); -} \ No newline at end of file +} + + +#[ink::test] +fn admin_transfer_node_ownership_err_if_not_admin() { + let mut contract = setup_contract(); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let not_admin_id = AccountId::from([0x00, 0xc9, 0x91, 0xf1, 0x63, 0x0f, 0xb4, 0x51, 0xf6, 0x6c, 0x9e, 0xa5, 0xc6, 0xdd, 0xf3, 0x33, 0xd8, 0x48, 0x75, 0xc6, 0x22, 0xf5, 0xd3, 0xde, 0x4a, 0x39, 0xe7, 0x71, 0x6f, 0x74,0xf0, 0x49]); + set_balance(not_admin_id, 1000 * TOKEN); + + set_caller_value(not_admin_id, CONTRACT_FEE_LIMIT); + contract.node_create( + new_node_key, + NodeParams::from("{\"url\":\"https://ddc-1.cere.network/storage/new\"}"), + 100, + 10 * TOKEN, + )?; + + let node_info = contract.node_get(new_node_key)?; + assert_eq!(node_info.node.provider_id, not_admin_id); + + let new_owner_id = AccountId::from([0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, 0x47, 0x16]); + set_balance(new_owner_id, 1000 * TOKEN); + + set_caller(not_admin_id); + + assert_eq!( + contract.admin_transfer_node_ownership( + new_node_key, + new_owner_id + ), + Err(OnlySuperAdmin) + ); +} + + +#[ink::test] +fn admin_transfer_node_ownership_err_if_provider_is_not_admin() { + let mut contract = setup_contract(); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let not_admin_id = AccountId::from([0x00, 0xc9, 0x91, 0xf1, 0x63, 0x0f, 0xb4, 0x51, 0xf6, 0x6c, 0x9e, 0xa5, 0xc6, 0xdd, 0xf3, 0x33, 0xd8, 0x48, 0x75, 0xc6, 0x22, 0xf5, 0xd3, 0xde, 0x4a, 0x39, 0xe7, 0x71, 0x6f, 0x74,0xf0, 0x49]); + set_balance(not_admin_id, 1000 * TOKEN); + + set_caller_value(not_admin_id, CONTRACT_FEE_LIMIT); + contract.node_create( + new_node_key, + NodeParams::from("{\"url\":\"https://ddc-1.cere.network/storage/new\"}"), + 100, + 10 * TOKEN, + )?; + + let node_info = contract.node_get(new_node_key)?; + assert_eq!(node_info.node.provider_id, not_admin_id); + + let new_owner_id = AccountId::from([0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, 0x47, 0x16]); + set_balance(new_owner_id, 1000 * TOKEN); + + set_caller(admin_id()); + + assert_eq!( + contract.admin_transfer_node_ownership( + new_node_key, + new_owner_id + ), + Err(NodeOwnerIsNotSuperAdmin) + ); +} + + +#[ink::test] +fn admin_transfer_node_ownership_ok() { + let mut contract = setup_contract(); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); + contract.node_create( + new_node_key, + NodeParams::from("{\"url\":\"https://ddc-1.cere.network/storage/new\"}"), + 100, + 10 * TOKEN, + )?; + + let node_info1 = contract.node_get(new_node_key)?; + assert_eq!(node_info1.node.provider_id, admin_id()); + + let new_owner_id = AccountId::from([0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, 0x47, 0x16]); + set_balance(new_owner_id, 1000 * TOKEN); + + set_caller(admin_id()); + contract.admin_transfer_node_ownership( + new_node_key, + new_owner_id + )?; + + let node_info2 = contract.node_get(new_node_key)?; + assert_eq!(node_info2.node.provider_id, new_owner_id); + + assert!( + matches!(get_events().pop().unwrap(), Event::NodeOwnershipTransferred(ev) if ev == + NodeOwnershipTransferred { + account_id: new_owner_id, + node_key: new_node_key + } + ) + ); +} + + +#[ink::test] +fn admin_transfer_cdn_node_ownership_err_if_not_admin() { + let mut contract = setup_contract(); + + let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let not_admin_id = AccountId::from([0x00, 0xc9, 0x91, 0xf1, 0x63, 0x0f, 0xb4, 0x51, 0xf6, 0x6c, 0x9e, 0xa5, 0xc6, 0xdd, 0xf3, 0x33, 0xd8, 0x48, 0x75, 0xc6, 0x22, 0xf5, 0xd3, 0xde, 0x4a, 0x39, 0xe7, 0x71, 0x6f, 0x74,0xf0, 0x49]); + set_balance(not_admin_id, 1000 * TOKEN); + + set_caller_value(not_admin_id, CONTRACT_FEE_LIMIT); + contract.cdn_node_create( + new_cdn_node_key, + CdnNodeParams::from("{\"url\":\"https://ddc-1.cere.network/cdn/new\"}"), + )?; + + let cdn_node_info = contract.cdn_node_get(new_cdn_node_key)?; + assert_eq!(cdn_node_info.cdn_node.provider_id, not_admin_id); + + let new_owner_id = AccountId::from([0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, 0x47, 0x16]); + set_balance(new_owner_id, 1000 * TOKEN); + + set_caller(not_admin_id); + + assert_eq!( + contract.admin_transfer_cdn_node_ownership( + new_cdn_node_key, + new_owner_id + ), + + Err(OnlySuperAdmin) + ); +} + + +#[ink::test] +fn admin_transfer_cdn_node_ownership_err_if_provider_is_not_admin() { + let mut contract = setup_contract(); + + let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let not_admin_id = AccountId::from([0x00, 0xc9, 0x91, 0xf1, 0x63, 0x0f, 0xb4, 0x51, 0xf6, 0x6c, 0x9e, 0xa5, 0xc6, 0xdd, 0xf3, 0x33, 0xd8, 0x48, 0x75, 0xc6, 0x22, 0xf5, 0xd3, 0xde, 0x4a, 0x39, 0xe7, 0x71, 0x6f, 0x74,0xf0, 0x49]); + set_balance(not_admin_id, 1000 * TOKEN); + + set_caller_value(not_admin_id, CONTRACT_FEE_LIMIT); + contract.cdn_node_create( + new_cdn_node_key, + CdnNodeParams::from("{\"url\":\"https://ddc-1.cere.network/cdn/new\"}"), + )?; + + let cdn_node_info = contract.cdn_node_get(new_cdn_node_key)?; + assert_eq!(cdn_node_info.cdn_node.provider_id, not_admin_id); + + let new_owner_id = AccountId::from([0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, 0x47, 0x16]); + set_balance(new_owner_id, 1000 * TOKEN); + + set_caller(admin_id()); + + assert_eq!( + contract.admin_transfer_cdn_node_ownership( + new_cdn_node_key, + new_owner_id + ), + Err(CdnNodeOwnerIsNotSuperAdmin) + ); +} + + +#[ink::test] +fn admin_transfer_cdn_node_ownership_ok() { + let mut contract = setup_contract(); + + let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); + contract.cdn_node_create( + new_cdn_node_key, + CdnNodeParams::from("{\"url\":\"https://ddc-1.cere.network/cdn/new\"}"), + )?; + + let cdn_node_info1 = contract.cdn_node_get(new_cdn_node_key)?; + assert_eq!(cdn_node_info1.cdn_node.provider_id, admin_id()); + + let new_owner_id = AccountId::from([0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, 0x47, 0x16]); + set_balance(new_owner_id, 1000 * TOKEN); + + set_caller(admin_id()); + contract.admin_transfer_cdn_node_ownership( + new_cdn_node_key, + new_owner_id + )?; + + let cdn_node_info2 = contract.cdn_node_get(new_cdn_node_key)?; + assert_eq!(cdn_node_info2.cdn_node.provider_id, new_owner_id); + + assert!( + matches!(get_events().pop().unwrap(), Event::CdnNodeOwnershipTransferred(ev) if ev == + CdnNodeOwnershipTransferred { + account_id: new_owner_id, + cdn_node_key: new_cdn_node_key + } + ) + ); +} From 8c63041a1cdee6b02a2c3c34c0dbfc0c3108262e Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 14:18:02 +0200 Subject: [PATCH 62/89] fix(lib): reducing code size by merging modules --- bucket/ddc_bucket/account/store.rs | 4 +- bucket/ddc_bucket/bucket/entity.rs | 17 +++- bucket/ddc_bucket/bucket/messages.rs | 100 ++++++++++++-------- bucket/ddc_bucket/bucket/store.rs | 114 ++++++++++++++++++++--- bucket/ddc_bucket/buckets_perms/mod.rs | 3 - bucket/ddc_bucket/buckets_perms/store.rs | 90 ------------------ bucket/ddc_bucket/cash.rs | 4 +- bucket/ddc_bucket/cdn_node/entity.rs | 5 +- bucket/ddc_bucket/cdn_node/store.rs | 4 +- bucket/ddc_bucket/cluster/entity.rs | 6 +- bucket/ddc_bucket/cluster/messages.rs | 3 +- bucket/ddc_bucket/cluster/store.rs | 6 +- bucket/ddc_bucket/committer/store.rs | 6 +- bucket/ddc_bucket/currency.rs | 4 +- bucket/ddc_bucket/network_fee.rs | 6 +- bucket/ddc_bucket/node/entity.rs | 4 +- bucket/ddc_bucket/node/store.rs | 4 +- bucket/ddc_bucket/params/messages.rs | 12 --- bucket/ddc_bucket/params/mod.rs | 4 - bucket/ddc_bucket/params/store.rs | 45 --------- bucket/ddc_bucket/perm/store.rs | 4 +- bucket/ddc_bucket/protocol/store.rs | 4 +- bucket/ddc_bucket/tests/env_utils.rs | 1 + bucket/ddc_bucket/tests/test_bucket.rs | 2 + bucket/ddc_bucket/topology/store.rs | 4 +- bucket/lib.rs | 14 +-- 26 files changed, 220 insertions(+), 250 deletions(-) delete mode 100644 bucket/ddc_bucket/buckets_perms/mod.rs delete mode 100644 bucket/ddc_bucket/buckets_perms/store.rs delete mode 100644 bucket/ddc_bucket/params/messages.rs delete mode 100644 bucket/ddc_bucket/params/mod.rs delete mode 100644 bucket/ddc_bucket/params/store.rs diff --git a/bucket/ddc_bucket/account/store.rs b/bucket/ddc_bucket/account/store.rs index 18a69245..fff58bbe 100644 --- a/bucket/ddc_bucket/account/store.rs +++ b/bucket/ddc_bucket/account/store.rs @@ -9,12 +9,12 @@ use crate::ddc_bucket::{ }; use crate::ddc_bucket::currency::CurrencyConverter; use crate::ddc_bucket::flow::Flow; -use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; +use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_prelude::vec::Vec; use super::entity::Account; #[derive(Default, SpreadLayout, SpreadAllocate)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct AccountStore( pub Mapping, pub CurrencyConverter, diff --git a/bucket/ddc_bucket/bucket/entity.rs b/bucket/ddc_bucket/bucket/entity.rs index e6adc099..53bd923c 100644 --- a/bucket/ddc_bucket/bucket/entity.rs +++ b/bucket/ddc_bucket/bucket/entity.rs @@ -1,6 +1,7 @@ //! The data structure of Buckets. use ink_prelude::vec::Vec; +use ink_prelude::string::String; use ink_storage::traits::{SpreadAllocate, PackedAllocate, PackedLayout, SpreadLayout}; use scale::{Decode, Encode}; use ink_primitives::Key; @@ -10,10 +11,10 @@ use crate::ddc_bucket::{ }; use crate::ddc_bucket::flow::Flow; use crate::ddc_bucket::node::entity::Resource; -use crate::ddc_bucket::params::store::Params; + pub type BucketId = u32; -pub type BucketParams = Params; +pub type BucketParams = String; #[derive(Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] @@ -24,6 +25,7 @@ pub struct Bucket { pub resource_reserved: Resource, pub public_availability: bool, pub resource_consumption_cap: Resource, + pub bucket_params: BucketParams } // https://use.ink/3.x/ink-vs-solidity#nested-mappings--custom--advanced-structures @@ -58,6 +60,8 @@ pub struct BucketStatus { pub rent_covered_until_ms: u64, } +pub const BUCKET_PARAMS_MAX_LEN: usize = 100_000; + impl Bucket { pub fn only_owner(&self, caller: AccountId) -> Result<()> { if self.owner_id == caller { Ok(()) } else { Err(OnlyOwner) } @@ -78,6 +82,15 @@ impl Bucket { pub fn change_owner(&mut self, owner_id: AccountId) { self.owner_id = owner_id; } + + pub fn set_params(&mut self, bucket_params: BucketParams) -> Result<()> { + if bucket_params.len() > BUCKET_PARAMS_MAX_LEN { + return Err(ParamsSizeExceedsLimit); + } + self.bucket_params = bucket_params; + Ok(()) + } + } impl From for BucketInStatus { diff --git a/bucket/ddc_bucket/bucket/messages.rs b/bucket/ddc_bucket/bucket/messages.rs index e7cd9155..0a55f498 100644 --- a/bucket/ddc_bucket/bucket/messages.rs +++ b/bucket/ddc_bucket/bucket/messages.rs @@ -3,7 +3,7 @@ use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; -use crate::ddc_bucket::{AccountId, BucketAllocated, BucketCreated, BucketSettlePayment, BucketAvailabilityUpdated, DdcBucket, Result}; +use crate::ddc_bucket::{AccountId, BucketAllocated, BucketCreated, BucketSettlePayment, BucketAvailabilityUpdated, BucketParamsSet, DdcBucket, Result}; use crate::ddc_bucket::cluster::entity::{Cluster, ClusterId}; use crate::ddc_bucket::node::entity::Resource; @@ -13,25 +13,24 @@ impl DdcBucket { pub fn message_bucket_create(&mut self, bucket_params: BucketParams, cluster_id: ClusterId, owner_id: Option) -> Result { let owner_id = owner_id.unwrap_or(Self::env().caller()); self.accounts.create_if_not_exist(owner_id); - let bucket_id = self.buckets.create(owner_id, cluster_id); - let params_id = self.bucket_params.create(bucket_params)?; - assert_eq!(bucket_id, params_id); + let bucket_id = self.buckets.create(owner_id, cluster_id, bucket_params); Self::env().emit_event(BucketCreated { bucket_id, owner_id }); Ok(bucket_id) } pub fn message_bucket_change_owner(&mut self, bucket_id: BucketId, owner_id: AccountId) -> Result<()> { let caller = Self::env().caller(); - let bucket = self.buckets.get_mut(bucket_id)?; + let mut bucket = self.buckets.get(bucket_id)?; bucket.only_owner(caller)?; bucket.change_owner(owner_id); + self.buckets.update(bucket_id, &bucket)?; Ok(()) } pub fn message_bucket_alloc_into_cluster(&mut self, bucket_id: BucketId, resource: Resource) -> Result<()> { - let bucket = self.buckets.get_mut(bucket_id)?; + let mut bucket = self.buckets.get(bucket_id)?; let mut cluster = self.clusters.get(bucket.cluster_id)?; - Self::only_owner_or_cluster_manager(bucket, &cluster)?; + Self::only_owner_or_cluster_manager(&bucket, &cluster)?; cluster.take_resource(resource)?; self.clusters.update(bucket.cluster_id, &cluster)?; @@ -42,13 +41,14 @@ impl DdcBucket { let now_ms = Self::env().block_timestamp(); self.accounts.increase_flow(now_ms, rent, &mut bucket.flow)?; + self.buckets.update(bucket_id, &bucket)?; Self::env().emit_event(BucketAllocated { bucket_id, cluster_id: bucket.cluster_id, resource }); Ok(()) } pub fn message_bucket_settle_payment(&mut self, bucket_id: BucketId) -> Result<()> { - let bucket = self.buckets.get_mut(bucket_id)?; + let mut bucket = self.buckets.get(bucket_id)?; let now_ms = Self::env().block_timestamp(); let cash = self.accounts.settle_flow(now_ms, &mut bucket.flow)?; @@ -56,18 +56,21 @@ impl DdcBucket { let mut cluster = self.clusters.get(bucket.cluster_id)?; cluster.revenues.increase(cash); self.clusters.update(bucket.cluster_id, &cluster)?; + self.buckets.update(bucket_id, &bucket)?; Self::env().emit_event(BucketSettlePayment { bucket_id, cluster_id: bucket.cluster_id }); Ok(()) } - pub fn message_bucket_change_params(&mut self, bucket_id: BucketId, params: BucketParams) -> Result<()> { + pub fn message_bucket_change_params(&mut self, bucket_id: BucketId, bucket_params: BucketParams) -> Result<()> { let caller = Self::env().caller(); - let bucket = self.buckets.get(bucket_id)?; + let mut bucket = self.buckets.get(bucket_id)?; bucket.only_owner(caller)?; - - Self::impl_change_params(&mut self.bucket_params, bucket_id, params) + bucket.set_params(bucket_params.clone())?; + self.buckets.update(bucket_id, &bucket)?; + Self::env().emit_event(BucketParamsSet { bucket_id, bucket_params }); + Ok(()) } pub fn message_bucket_get(&self, bucket_id: BucketId) -> Result { @@ -78,7 +81,7 @@ impl DdcBucket { pub fn message_bucket_list(&self, offset: u32, limit: u32, filter_owner_id: Option) -> (Vec, u32) { let mut bucket_statuses = Vec::with_capacity(limit as usize); for bucket_id in offset..offset + limit { - let bucket = match self.buckets.0.get(bucket_id as usize) { + let bucket = match self.buckets.buckets.get(bucket_id) { None => break, // No more buckets, stop. Some(bucket) => bucket, }; @@ -95,89 +98,104 @@ impl DdcBucket { bucket_statuses.push(status), }; } - (bucket_statuses, self.buckets.0.len().try_into().unwrap()) + (bucket_statuses, self.buckets.next_bucket_id) } pub fn message_bucket_list_for_account(&self, owner_id: AccountId) -> Vec { - self.buckets.0 - .iter() - .filter(|bucket| bucket.owner_id == owner_id) - .cloned() - .collect() + let mut result : Vec = Vec::new(); + + for bucket_id in 0..self.buckets.next_bucket_id { + let bucket = self.buckets.get(bucket_id).unwrap(); + + if bucket.owner_id == owner_id { + result.push(bucket); + }; + } + + result } pub fn bucket_calculate_status(&self, bucket_id: BucketId, bucket: Bucket) -> Result { - let mut writer_ids = self.buckets_perms.get_bucket_readers(bucket_id); + let mut writer_ids = self.buckets.get_bucket_readers(bucket_id); writer_ids.push(bucket.owner_id); let rent_covered_until_ms = self.accounts.flow_covered_until(&bucket.flow)?; - let params = self.bucket_params.get(bucket_id)?.clone(); - let reader_ids = self.buckets_perms.get_bucket_readers(bucket_id); - Ok(BucketStatus { bucket_id, bucket: bucket.into(), params, writer_ids, reader_ids, rent_covered_until_ms }) + let reader_ids = self.buckets.get_bucket_readers(bucket_id); + let bucket_params = bucket.bucket_params.clone(); + + Ok(BucketStatus { bucket_id, params: bucket_params, bucket: bucket.into(), writer_ids, reader_ids, rent_covered_until_ms }) } pub fn message_bucket_set_resource_cap(&mut self, bucket_id: BucketId, new_resource_cap: Resource) -> Result<()> { - let bucket = self.buckets.get_mut(bucket_id)?; + let mut bucket = self.buckets.get(bucket_id)?; let cluster = self.clusters.get(bucket.cluster_id)?; - Self::only_owner_or_cluster_manager(bucket, &cluster)?; + Self::only_owner_or_cluster_manager(&bucket, &cluster)?; bucket.set_cap(new_resource_cap); + self.buckets.update(bucket_id, &bucket)?; + Ok(()) } pub fn message_bucket_set_availability(&mut self, bucket_id: BucketId, public_availability: bool) -> Result<()> { - let bucket = self.buckets.get_mut(bucket_id)?; + let mut bucket = self.buckets.get(bucket_id)?; let cluster = self.clusters.get(bucket.cluster_id)?; - Self::only_owner_or_cluster_manager(bucket, &cluster)?; + Self::only_owner_or_cluster_manager(&bucket, &cluster)?; bucket.set_availability(public_availability); + self.buckets.update(bucket_id, &bucket)?; + Self::env().emit_event(BucketAvailabilityUpdated { bucket_id, public_availability }); Ok(()) } pub fn message_get_bucket_writers(&mut self, bucket_id: BucketId) -> Result> { - let writers = self.buckets_perms.get_bucket_writers(bucket_id); + let writers = self.buckets.get_bucket_writers(bucket_id); Ok(writers) } pub fn message_grant_writer_permission(&mut self, bucket_id: BucketId, writer: AccountId) -> Result<()> { - let bucket = self.buckets.get_mut(bucket_id)?; + let bucket = self.buckets.get(bucket_id)?; let cluster = self.clusters.get(bucket.cluster_id)?; - Self::only_owner_or_cluster_manager(bucket, &cluster)?; - self.buckets_perms.grant_writer_permission(bucket_id, writer).unwrap(); + Self::only_owner_or_cluster_manager(&bucket, &cluster)?; + self.buckets.grant_writer_permission(bucket_id, writer).unwrap(); + Ok(()) } pub fn message_revoke_writer_permission(&mut self, bucket_id: BucketId, writer: AccountId) -> Result<()> { - let bucket = self.buckets.get_mut(bucket_id)?; + let bucket = self.buckets.get(bucket_id)?; let cluster = self.clusters.get(bucket.cluster_id)?; - Self::only_owner_or_cluster_manager(bucket, &cluster)?; - self.buckets_perms.revoke_writer_permission(bucket_id, writer).unwrap(); + Self::only_owner_or_cluster_manager(&bucket, &cluster)?; + self.buckets.revoke_writer_permission(bucket_id, writer).unwrap(); + Ok(()) } pub fn message_get_bucket_readers(&mut self, bucket_id: BucketId) -> Result> { - let readers = self.buckets_perms.get_bucket_readers(bucket_id); + let readers = self.buckets.get_bucket_readers(bucket_id); Ok(readers) } pub fn message_grant_reader_permission(&mut self, bucket_id: BucketId, reader: AccountId) -> Result<()> { - let bucket = self.buckets.get_mut(bucket_id)?; + let bucket = self.buckets.get(bucket_id)?; let cluster = self.clusters.get(bucket.cluster_id)?; - Self::only_owner_or_cluster_manager(bucket, &cluster)?; - self.buckets_perms.grant_reader_permission(bucket_id, reader).unwrap(); + Self::only_owner_or_cluster_manager(&bucket, &cluster)?; + self.buckets.grant_reader_permission(bucket_id, reader).unwrap(); + Ok(()) } pub fn message_revoke_reader_permission(&mut self, bucket_id: BucketId, reader: AccountId) -> Result<()> { - let bucket = self.buckets.get_mut(bucket_id)?; + let bucket = self.buckets.get(bucket_id)?; let cluster = self.clusters.get(bucket.cluster_id)?; - Self::only_owner_or_cluster_manager(bucket, &cluster)?; - self.buckets_perms.revoke_reader_permission(bucket_id, reader).unwrap(); + Self::only_owner_or_cluster_manager(&bucket, &cluster)?; + self.buckets.revoke_reader_permission(bucket_id, reader).unwrap(); + Ok(()) } diff --git a/bucket/ddc_bucket/bucket/store.rs b/bucket/ddc_bucket/bucket/store.rs index 311e6293..486b44bb 100644 --- a/bucket/ddc_bucket/bucket/store.rs +++ b/bucket/ddc_bucket/bucket/store.rs @@ -1,22 +1,29 @@ -//! The store to create and access Buckets. - -use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; +use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_prelude::vec::Vec; - +use ink_storage::Mapping; use crate::ddc_bucket::{AccountId, Error::*, Result}; use crate::ddc_bucket::cluster::entity::ClusterId; use crate::ddc_bucket::flow::Flow; use crate::ddc_bucket::schedule::Schedule; +use super::entity::{Bucket, BucketId, BucketParams}; + -use super::entity::{Bucket, BucketId}; #[derive(SpreadAllocate, SpreadLayout, Default)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] -pub struct BucketStore(pub Vec); +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] +pub struct BucketStore { + pub next_bucket_id: u32, + pub buckets: Mapping, + pub writers: Mapping>, + pub readers: Mapping> +} impl BucketStore { #[must_use] - pub fn create(&mut self, owner_id: AccountId, cluster_id: ClusterId) -> BucketId { + pub fn create(&mut self, owner_id: AccountId, cluster_id: ClusterId, bucket_params: BucketParams) -> BucketId { + let bucket_id = self.next_bucket_id; + self.next_bucket_id = self.next_bucket_id + 1; + let bucket = Bucket { owner_id, cluster_id, @@ -24,17 +31,96 @@ impl BucketStore { resource_reserved: 0, resource_consumption_cap: 0, public_availability: false, + bucket_params }; - let bucket_id: BucketId = self.0.len().try_into().unwrap(); - self.0.push(bucket); + + self.buckets.insert(&bucket_id, &bucket); bucket_id } - pub fn get(&self, bucket_id: BucketId) -> Result<&Bucket> { - self.0.get(bucket_id as usize).ok_or(BucketDoesNotExist) + pub fn get(&self, bucket_id: BucketId) -> Result { + self.buckets.get(bucket_id).ok_or(BucketDoesNotExist) + } + + pub fn update(&mut self, bucket_id: BucketId, bucket: &Bucket) -> Result<()> { + if !self.buckets.contains(&bucket_id) { + Err(BucketDoesNotExist) + } else { + self.buckets.insert(bucket_id, bucket); + Ok(()) + } } - pub fn get_mut(&mut self, bucket_id: BucketId) -> Result<&mut Bucket> { - self.0.get_mut(bucket_id as usize).ok_or(BucketDoesNotExist) + // get accounts with permission for bucket writing + pub fn get_bucket_writers(&self, key: BucketId) -> Vec { + let writers : Vec = self.writers.get(&key) + .unwrap_or(Vec::new()) + .iter() + .cloned() + .collect(); + return writers; } + + // grant permission for bucket writing for some account + pub fn grant_writer_permission(&mut self, key: BucketId, writer: AccountId) -> Result<()> { + if !self.writers.contains(&key) { + let empty_vec: Vec = Vec::new(); + self.writers.insert(key, &empty_vec); + } + + let mut writers = self.writers.get(&key).unwrap(); + writers.push(writer); + self.writers.insert(key, &writers); + + Ok(()) + } + + // revoke permission for bucket writing for some account + pub fn revoke_writer_permission(&mut self, key: BucketId, writer: AccountId) -> Result<()> { + let mut writers = self.writers.get(&key).unwrap(); + if let Some(pos) = writers.iter().position(|x| *x == writer) { + writers.remove(pos); + self.writers.insert(key, &writers); + } + + Ok(()) + } + + // get accounts with permission for bucket reading + pub fn get_bucket_readers(&self, key: BucketId) -> Vec { + let readers = self.readers.get(&key) + .unwrap_or(Vec::new()) + .iter() + .cloned() + .collect(); + + return readers; + } + + // grant permission for bucket reading for some account + pub fn grant_reader_permission(&mut self, key: BucketId, reader: AccountId) -> Result<()> { + if !self.readers.contains(&key) { + let empty_vec: Vec = Vec::new(); + self.readers.insert(key, &empty_vec); + } + + let mut readers = self.readers.get(&key).unwrap(); + readers.push(reader); + self.readers.insert(key, &readers); + + Ok(()) + } + + // revoke permission for bucket writing for some account + pub fn revoke_reader_permission(&mut self, key: BucketId, reader: AccountId) -> Result<()> { + let mut readers = self.readers.get(&key).unwrap(); + + if let Some(pos) = readers.iter().position(|x| *x == reader) { + readers.remove(pos); + self.readers.insert(key, &readers); + } + + Ok(()) + } + } diff --git a/bucket/ddc_bucket/buckets_perms/mod.rs b/bucket/ddc_bucket/buckets_perms/mod.rs deleted file mode 100644 index c8b20147..00000000 --- a/bucket/ddc_bucket/buckets_perms/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -//! Bucket perms management. - -pub mod store; diff --git a/bucket/ddc_bucket/buckets_perms/store.rs b/bucket/ddc_bucket/buckets_perms/store.rs deleted file mode 100644 index 147baf90..00000000 --- a/bucket/ddc_bucket/buckets_perms/store.rs +++ /dev/null @@ -1,90 +0,0 @@ -//! The store to adjust write/read permissions for DDC Buckets - -use crate::ddc_bucket::{AccountId, BucketId, Result}; - -use ink_prelude::vec::Vec; -use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; -use ink_storage::Mapping; - -#[derive(SpreadAllocate, SpreadLayout, Default)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] -pub struct BucketsPermsStore { - writers: Mapping>, - readers: Mapping> -} - -impl BucketsPermsStore { - - // get accounts with permission for bucket writing - pub fn get_bucket_writers(&self, key: BucketId) -> Vec { - let writers : Vec = self.writers.get(&key) - .unwrap_or(Vec::new()) - .iter() - .cloned() - .collect(); - return writers; - } - - // grant permission for bucket writing for some account - pub fn grant_writer_permission(&mut self, key: BucketId, writer: AccountId) -> Result<()> { - if !self.writers.contains(&key) { - let empty_vec: Vec = Vec::new(); - self.writers.insert(key, &empty_vec); - } - - let mut writers = self.writers.get(&key).unwrap(); - writers.push(writer); - self.writers.insert(key, &writers); - - Ok(()) - } - - // revoke permission for bucket writing for some account - pub fn revoke_writer_permission(&mut self, key: BucketId, writer: AccountId) -> Result<()> { - let mut writers = self.writers.get(&key).unwrap(); - if let Some(pos) = writers.iter().position(|x| *x == writer) { - writers.remove(pos); - self.writers.insert(key, &writers); - } - - Ok(()) - } - - // get accounts with permission for bucket reading - pub fn get_bucket_readers(&self, key: BucketId) -> Vec { - let readers = self.readers.get(&key) - .unwrap_or(Vec::new()) - .iter() - .cloned() - .collect(); - - return readers; - } - - // grant permission for bucket reading for some account - pub fn grant_reader_permission(&mut self, key: BucketId, reader: AccountId) -> Result<()> { - if !self.readers.contains(&key) { - let empty_vec: Vec = Vec::new(); - self.readers.insert(key, &empty_vec); - } - - let mut readers = self.readers.get(&key).unwrap(); - readers.push(reader); - self.readers.insert(key, &readers); - - Ok(()) - } - - // revoke permission for bucket writing for some account - pub fn revoke_reader_permission(&mut self, key: BucketId, reader: AccountId) -> Result<()> { - let mut readers = self.readers.get(&key).unwrap(); - - if let Some(pos) = readers.iter().position(|x| *x == reader) { - readers.remove(pos); - self.readers.insert(key, &readers); - } - - Ok(()) - } - -} diff --git a/bucket/ddc_bucket/cash.rs b/bucket/ddc_bucket/cash.rs index 9c76b8d9..20766771 100644 --- a/bucket/ddc_bucket/cash.rs +++ b/bucket/ddc_bucket/cash.rs @@ -2,7 +2,7 @@ //! //! These data structures facilitate the correctness of money-related calculations using the Rust type system. -use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout, StorageLayout}; +use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout}; use ink_storage::traits::KeyPtr; use scale::{Decode, Encode}; @@ -13,7 +13,7 @@ use crate::ddc_bucket::Error::InsufficientBalance; /// Cash represents some value that was taken from someone, and that must be credited to someone. #[must_use] #[derive(Clone, Copy, PartialEq, Encode, Decode, SpreadLayout, PackedLayout)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct Cash(pub Balance); impl SpreadAllocate for Cash { diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index 717cd11a..7593f2d4 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -4,11 +4,12 @@ use ink_storage::traits::{SpreadAllocate, PackedLayout, SpreadLayout, PackedAllo use scale::{Decode, Encode}; use ink_primitives::Key; use crate::ddc_bucket::{AccountId, Balance, ClusterId, NodeStatusInCluster, Error::*, Result}; -use crate::ddc_bucket::params::store::Params; +use ink_prelude::string::String; + pub type ProviderId = AccountId; pub type CdnNodeKey = AccountId; -pub type CdnNodeParams = Params; +pub type CdnNodeParams = String; pub type Resource = u32; #[derive(Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] diff --git a/bucket/ddc_bucket/cdn_node/store.rs b/bucket/ddc_bucket/cdn_node/store.rs index d2d5d8f9..402df082 100644 --- a/bucket/ddc_bucket/cdn_node/store.rs +++ b/bucket/ddc_bucket/cdn_node/store.rs @@ -1,6 +1,6 @@ //! The store where to create and access Nodes. -use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; +use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_storage::Mapping; use ink_prelude::vec::Vec; @@ -9,7 +9,7 @@ use super::entity::{CdnNode, CdnNodeKey, CdnNodeParams}; #[derive(SpreadAllocate, SpreadLayout, Default)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct CdnNodeStore { pub cdn_nodes: Mapping, // This vector is temporal and must be replaced with an offchain indexer diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 688e8c66..1aa5c7e6 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -1,18 +1,18 @@ //! The data structure of Clusters. use ink_prelude::vec::Vec; +use ink_prelude::string::String; use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout, PackedAllocate}; use scale::{Decode, Encode}; use ink_primitives::Key; use crate::ddc_bucket::cash::{Cash, Payable}; use crate::ddc_bucket::node::entity::{Resource, NodeKey}; use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; - -use crate::ddc_bucket::params::store::Params; use crate::ddc_bucket::Error::{OnlyClusterManager, InsufficientBalance}; use crate::ddc_bucket::{AccountId, Balance, VNodeToken, Result, Error::*}; + pub type ClusterId = u32; -pub type ClusterParams = Params; +pub type ClusterParams = String; #[derive(Clone, PartialEq, Encode, Decode, SpreadAllocate, PackedLayout, SpreadLayout)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index ccba19e2..df95b355 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -539,10 +539,11 @@ impl DdcBucket { // Go through buckets and deduct used resources for &(bucket_id, resources_used) in aggregates_buckets.iter() { - let bucket = self.buckets.get_mut(bucket_id)?; + let mut bucket = self.buckets.get(bucket_id)?; if bucket.resource_consumption_cap <= resources_used { bucket.resource_consumption_cap -= resources_used; + self.buckets.update(bucket_id, &bucket)?; } } diff --git a/bucket/ddc_bucket/cluster/store.rs b/bucket/ddc_bucket/cluster/store.rs index 2a942ab7..de973076 100644 --- a/bucket/ddc_bucket/cluster/store.rs +++ b/bucket/ddc_bucket/cluster/store.rs @@ -1,16 +1,16 @@ //! The store where to create and access Clusters by ID. -use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; +use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_storage::Mapping; use crate::ddc_bucket::{AccountId, Error::*, Result}; use super::entity::{Cluster, ClusterId, ClusterParams}; #[derive(SpreadAllocate, SpreadLayout, Default)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct ClusterStore { + pub next_cluster_id: u32, pub clusters: Mapping, - pub next_cluster_id: u32 } impl ClusterStore { diff --git a/bucket/ddc_bucket/committer/store.rs b/bucket/ddc_bucket/committer/store.rs index 7216e964..6b2ded3b 100644 --- a/bucket/ddc_bucket/committer/store.rs +++ b/bucket/ddc_bucket/committer/store.rs @@ -1,6 +1,6 @@ use crate::ddc_bucket::{AccountId, Hash, CdnNodeKey}; -use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout, PackedLayout}; +use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout}; use ink_prelude::vec::Vec; use ink_storage::Mapping; @@ -40,7 +40,7 @@ pub struct Commit { } #[derive(Default, Copy, Clone, SpreadAllocate, SpreadLayout, scale::Encode, scale::Decode, Debug)] -#[cfg_attr(feature = "std", derive(::scale_info::TypeInfo, StorageLayout))] +#[cfg_attr(feature = "std", derive(::scale_info::TypeInfo, ink_storage::traits::StorageLayout))] pub struct EraConfig { start: u64, interval: u64, @@ -49,7 +49,7 @@ pub struct EraConfig { } #[derive(Default, SpreadAllocate, SpreadLayout, Debug)] -#[cfg_attr(feature = "std", derive(StorageLayout))] +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout))] pub struct CommitterStore { operator_id: AccountId, commits: Mapping>, diff --git a/bucket/ddc_bucket/currency.rs b/bucket/ddc_bucket/currency.rs index 880e937c..713a39d5 100644 --- a/bucket/ddc_bucket/currency.rs +++ b/bucket/ddc_bucket/currency.rs @@ -1,6 +1,6 @@ //! The privileged interface for admin tasks. -use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; +use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_storage::traits::KeyPtr; use crate::ddc_bucket::{Balance, TOKEN}; @@ -10,7 +10,7 @@ pub type USD = Balance; #[derive(SpreadLayout)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct CurrencyConverter(Balance /* how many USD for PRECISION CERE */); const PRECISION: Balance = 10_000_000; diff --git a/bucket/ddc_bucket/network_fee.rs b/bucket/ddc_bucket/network_fee.rs index 25e6b4cf..72de6a0c 100644 --- a/bucket/ddc_bucket/network_fee.rs +++ b/bucket/ddc_bucket/network_fee.rs @@ -1,6 +1,6 @@ //! This module captures fees on behalf of the entire Cere network. -use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; +use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use scale::{Decode, Encode}; use crate::ddc_bucket::{AccountId, Balance, DdcBucket, Result}; @@ -12,7 +12,7 @@ pub type BasisPoints = Balance; const BP: BasisPoints = 10_000; // 100% #[derive(SpreadAllocate, SpreadLayout, Default)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct NetworkFeeStore( pub FeeConfig, ); @@ -25,7 +25,7 @@ impl NetworkFeeStore { /// The configuration of fees. #[derive(SpreadAllocate, SpreadLayout, Default, Decode, Encode)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug, scale_info::TypeInfo))] +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug, scale_info::TypeInfo))] pub struct FeeConfig { /// The fee rate from cluster revenues to the overall network. In basis points (1% of 1%). pub network_fee_bp: BasisPoints, diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index 29b2943b..0ff3715e 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -2,9 +2,9 @@ use ink_storage::traits::{SpreadAllocate, PackedLayout, SpreadLayout, PackedAllocate}; use ink_prelude::vec::Vec; +use ink_prelude::string::String; use scale::{Decode, Encode}; -use crate::ddc_bucket::params::store::Params; use crate::ddc_bucket::{AccountId, Balance, VNodeToken, Error::*, Result}; use crate::ddc_bucket::cluster::entity::ClusterId; @@ -13,7 +13,7 @@ use ink_primitives::Key; pub type ProviderId = AccountId; pub type NodeKey = AccountId; -pub type NodeParams = Params; +pub type NodeParams = String; pub type Resource = u32; #[derive(Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] diff --git a/bucket/ddc_bucket/node/store.rs b/bucket/ddc_bucket/node/store.rs index 0769e998..69495574 100644 --- a/bucket/ddc_bucket/node/store.rs +++ b/bucket/ddc_bucket/node/store.rs @@ -1,6 +1,6 @@ //! The store where to create and access Nodes. -use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; +use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_prelude::vec::Vec; use ink_storage::Mapping; @@ -10,7 +10,7 @@ use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; use super::entity::{Node, NodeKey, NodeParams, Resource}; #[derive(SpreadAllocate, SpreadLayout, Default)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct NodeStore { pub nodes: Mapping, // This pagination vector is temporal and must be replaced with an offchain indexer diff --git a/bucket/ddc_bucket/params/messages.rs b/bucket/ddc_bucket/params/messages.rs deleted file mode 100644 index 92b7d5ab..00000000 --- a/bucket/ddc_bucket/params/messages.rs +++ /dev/null @@ -1,12 +0,0 @@ -//! The public interface to change Params. - -use crate::ddc_bucket::{DdcBucket, Result}; - -use super::store::{Params, ParamsId, ParamsStore}; - -impl DdcBucket { - pub fn impl_change_params(store: &mut ParamsStore, params_id: ParamsId, params: Params) -> Result<()> { - store.change(params_id, params)?; - Ok(()) - } -} \ No newline at end of file diff --git a/bucket/ddc_bucket/params/mod.rs b/bucket/ddc_bucket/params/mod.rs deleted file mode 100644 index 94be958f..00000000 --- a/bucket/ddc_bucket/params/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -//! Params management. - -pub mod store; -pub mod messages; diff --git a/bucket/ddc_bucket/params/store.rs b/bucket/ddc_bucket/params/store.rs deleted file mode 100644 index ffe9a314..00000000 --- a/bucket/ddc_bucket/params/store.rs +++ /dev/null @@ -1,45 +0,0 @@ -//! The store where to create and access Nodes. - -use ink_prelude::string::String; -use ink_prelude::vec::Vec; -use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; - -use crate::ddc_bucket::{Error::*, Result}; - -pub type ParamsId = u32; -pub type Params = String; - -pub const PARAMS_MAX_LEN: usize = 100_000; - -#[derive(SpreadAllocate, SpreadLayout, Default)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] -pub struct ParamsStore(pub Vec); - -impl ParamsStore { - pub fn create(&mut self, params: Params) -> Result { - if params.len() > PARAMS_MAX_LEN { - return Err(ParamsSizeExceedsLimit); - } - let params_id: ParamsId = self.0.len().try_into().unwrap(); - self.0.push(params); - Ok(params_id) - } - - pub fn change(&mut self, params_id: ParamsId, params: Params) -> Result { - let current = self.0.get_mut(params_id as usize).ok_or(ParamsDoesNotExist)?; - - if params.len() > PARAMS_MAX_LEN { - return Err(ParamsSizeExceedsLimit); - } - let record_size = if params.len() > current.len() { - params.len() - current.len() - } else { 0 }; - - *current = params; - Ok(record_size) - } - - pub fn get(&self, params_id: ParamsId) -> Result<&Params> { - self.0.get(params_id as usize).ok_or(ParamsDoesNotExist) - } -} diff --git a/bucket/ddc_bucket/perm/store.rs b/bucket/ddc_bucket/perm/store.rs index 69a2edc4..32772d99 100644 --- a/bucket/ddc_bucket/perm/store.rs +++ b/bucket/ddc_bucket/perm/store.rs @@ -2,7 +2,7 @@ use ink_prelude::vec::Vec; use ink_storage::Mapping; -use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; +use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use scale::Encode; use crate::ddc_bucket::AccountId; @@ -15,7 +15,7 @@ pub type TrustedBy = AccountId; type PermKey = Vec; #[derive(SpreadAllocate, SpreadLayout, Default)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct PermStore(pub Mapping); // TODO: Switch to Mapping (must upgrade ink first). diff --git a/bucket/ddc_bucket/protocol/store.rs b/bucket/ddc_bucket/protocol/store.rs index 9a5ee390..94d42fdd 100644 --- a/bucket/ddc_bucket/protocol/store.rs +++ b/bucket/ddc_bucket/protocol/store.rs @@ -1,4 +1,4 @@ -use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout, StorageLayout}; +use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout}; use scale::{Decode, Encode}; @@ -6,7 +6,7 @@ use crate::ddc_bucket::{AccountId, Error::*, Result}; use crate::ddc_bucket::cash::{Cash, Payable}; #[derive(Default, Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug, scale_info::TypeInfo))] +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug, scale_info::TypeInfo))] pub struct ProtocolStore { pub admin: AccountId, pub fee_bp: u32, diff --git a/bucket/ddc_bucket/tests/env_utils.rs b/bucket/ddc_bucket/tests/env_utils.rs index 7402cdbf..dd44f128 100644 --- a/bucket/ddc_bucket/tests/env_utils.rs +++ b/bucket/ddc_bucket/tests/env_utils.rs @@ -86,6 +86,7 @@ pub fn print_events(events: &[Event]) { Event::NodeParamsSet(ev) => println!("EVENT {:?}", ev), Event::NodeOwnershipTransferred(ev) => println!("EVENT {:?}", ev), Event::CdnNodeOwnershipTransferred(ev) => println!("EVENT {:?}", ev), + Event::BucketParamsSet(ev) => println!("EVENT {:?}", ev), } } } diff --git a/bucket/ddc_bucket/tests/test_bucket.rs b/bucket/ddc_bucket/tests/test_bucket.rs index 697daffe..a5e5996e 100644 --- a/bucket/ddc_bucket/tests/test_bucket.rs +++ b/bucket/ddc_bucket/tests/test_bucket.rs @@ -116,6 +116,7 @@ fn bucket_create_ok() { // Check the structure of the bucket including the payment flow. let total_rent = ctx.rent_per_month * ctx.cluster_v_nodes.len() as Balance; + let bucket_params = BucketParams::from(""); let expect_bucket = Bucket { owner_id: test_bucket.owner_id, cluster_id: ctx.cluster_id, @@ -126,6 +127,7 @@ fn bucket_create_ok() { resource_reserved: test_bucket.resource, public_availability: false, resource_consumption_cap: 0, + bucket_params: bucket_params }; // Check the status of the bucket. diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index 33ad75e5..b9d5ed92 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -1,7 +1,7 @@ //! The store where to create and access Nodes. use ink_prelude::vec::Vec; use ink_storage::Mapping; -use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; +use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use crate::ddc_bucket::cluster::entity::ClusterId; use crate::ddc_bucket::node::entity::{NodeKey}; @@ -11,7 +11,7 @@ pub type VNodeToken = u64; pub type ClusterVNode = (ClusterId, VNodeToken); #[derive(SpreadAllocate, SpreadLayout, Default)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct TopologyStore { // virtual nodes assigned to a physical node v_nodes_map: Mapping>, diff --git a/bucket/lib.rs b/bucket/lib.rs index 187d417c..eea904da 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -18,7 +18,6 @@ pub mod ddc_bucket { use committer::store::*; use ink_storage::traits::SpreadAllocate; use node::{entity::*, store::*}; - use params::store::*; use perm::store::*; use topology::store::*; @@ -26,7 +25,6 @@ pub mod ddc_bucket { use crate::ddc_bucket::network_fee::{NetworkFeeStore, FeeConfig}; use crate::ddc_bucket::perm::entity::Permission; - use self::buckets_perms::store::BucketsPermsStore; use self::cdn_node::entity::{CdnNodeInfo, CdnNodeKey, CdnNodeParams}; use self::account::entity::Account; use self::protocol::store::ProtocolStore; @@ -35,7 +33,6 @@ pub mod ddc_bucket { pub mod account; pub mod admin; pub mod bucket; - pub mod buckets_perms; pub mod cash; pub mod cdn_node; pub mod cluster; @@ -44,7 +41,6 @@ pub mod ddc_bucket { pub mod flow; pub mod network_fee; pub mod node; - pub mod params; pub mod perm; pub mod protocol; pub mod schedule; @@ -56,8 +52,6 @@ pub mod ddc_bucket { #[derive(SpreadAllocate, Default)] pub struct DdcBucket { buckets: BucketStore, - buckets_perms: BucketsPermsStore, - bucket_params: ParamsStore, clusters: ClusterStore, cdn_nodes: CdnNodeStore, nodes: NodeStore, @@ -129,6 +123,14 @@ pub mod ddc_bucket { public_availability: bool, } + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct BucketParamsSet { + #[ink(topic)] + bucket_id: BucketId, + bucket_params: BucketParams, + } + impl DdcBucket { /// Create a new bucket and return its `bucket_id`. /// From 5adfe5660c4927319d3ec2d2929f71c3eb1cfe23 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 14:24:35 +0200 Subject: [PATCH 63/89] chore(accounts): accounts store adapted to upgrades --- bucket/ddc_bucket/account/messages.rs | 14 ++++++------- bucket/ddc_bucket/account/store.rs | 26 ++++++++++++------------ bucket/ddc_bucket/cluster/messages.rs | 4 ++-- bucket/ddc_bucket/tests/test_cluster.rs | 2 +- bucket/ddc_bucket/tests/test_currency.rs | 2 +- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/bucket/ddc_bucket/account/messages.rs b/bucket/ddc_bucket/account/messages.rs index d3f5739a..87a202f8 100644 --- a/bucket/ddc_bucket/account/messages.rs +++ b/bucket/ddc_bucket/account/messages.rs @@ -11,7 +11,7 @@ impl DdcBucket { // todo: remove this method as we can not support iterable data structures of arbitrary data size pub fn message_get_accounts(&self) -> Vec { - self.accounts.2.iter().cloned().collect() + self.accounts.accounts_keys.iter().cloned().collect() } pub fn message_account_deposit(&mut self) -> Result<()> { @@ -36,7 +36,7 @@ impl DdcBucket { let account_id = Self::env().caller(); if let Ok(mut account) = self.accounts.get(&account_id) { - let conv = &self.accounts.1; + let conv = &self.accounts.curr_converter; account.bond(time_ms, conv, bond_amount)?; self.accounts.save(&account_id, &account); Ok(()) @@ -68,12 +68,12 @@ impl DdcBucket { } pub fn message_account_get_usd_per_cere(&self) -> Balance { - self.accounts.1.to_usd(1 * TOKEN) + self.accounts.curr_converter.to_usd(1 * TOKEN) } pub fn message_account_set_usd_per_cere(&mut self, usd_per_cere: Balance) { self.only_with_permission(Permission::SetExchangeRate).unwrap(); - self.accounts.1.set_usd_per_cere(usd_per_cere) + self.accounts.curr_converter.set_usd_per_cere(usd_per_cere) } pub fn receive_cash() -> Cash { @@ -91,7 +91,7 @@ impl DdcBucket { fn _account_withdraw(&mut self, from: AccountId, payable: Payable) -> Result<()> { if let Ok(mut account) = self.accounts.get(&from) { let time_ms = Self::env().block_timestamp(); - let conv = &self.accounts.1; + let conv = &self.accounts.curr_converter; account.withdraw(time_ms, conv, payable)?; self.accounts.save(&from, &account); Ok(()) @@ -111,11 +111,11 @@ impl DdcBucket { } fn _account_get_net(&self, from: AccountId) -> Balance { - match self.accounts.0.get(&from) { + match self.accounts.accounts.get(&from) { None => 0, Some(account) => { let time_ms = Self::env().block_timestamp(); - let conv = &self.accounts.1; + let conv = &self.accounts.curr_converter; account.get_withdrawable(time_ms, conv) } } diff --git a/bucket/ddc_bucket/account/store.rs b/bucket/ddc_bucket/account/store.rs index fff58bbe..bf23ab86 100644 --- a/bucket/ddc_bucket/account/store.rs +++ b/bucket/ddc_bucket/account/store.rs @@ -15,37 +15,37 @@ use super::entity::Account; #[derive(Default, SpreadLayout, SpreadAllocate)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] -pub struct AccountStore( - pub Mapping, - pub CurrencyConverter, +pub struct AccountStore { + pub accounts: Mapping, // todo: remove this vector as it can store an arbitrary number of elements and easily exceed 16KB limit - pub Vec, -); + pub accounts_keys: Vec, + pub curr_converter: CurrencyConverter, +} impl AccountStore { /// Create a record for the given account if it does not exist yet. /// Does not return extra contract storage used, due to blockchain changes. pub fn create_if_not_exist(&mut self, account_id: AccountId) { - if !self.0.contains(account_id) { + if !self.accounts.contains(account_id) { let acc = Account::new(); - self.0.insert(account_id, &acc); - self.2.push(account_id); + self.accounts.insert(account_id, &acc); + self.accounts_keys.push(account_id); }; } pub fn balance(&self, account_id: &AccountId) -> Balance { - match self.0.get(account_id) { + match self.accounts.get(account_id) { None => 0, Some(account) => account.deposit.peek(), } } pub fn get(&self, account_id: &AccountId) -> Result { - self.0.get(account_id).ok_or(AccountDoesNotExist) + self.accounts.get(account_id).ok_or(AccountDoesNotExist) } pub fn save(&mut self, account_id: &AccountId, account: &Account) { - self.0.insert(account_id, account) + self.accounts.insert(account_id, account) } /// Increase the rate of the given flow starting from the given time. @@ -63,7 +63,7 @@ impl AccountStore { pub fn settle_flow(&mut self, now_ms: u64, flow: &mut Flow) -> Result { let flowed_usd = flow.schedule.take_value_at_time(now_ms); - let flowed_cere = self.1.to_cere(flowed_usd); + let flowed_cere = self.curr_converter.to_cere(flowed_usd); let (payable, cash) = Cash::borrow_payable_cash(flowed_cere); let mut account = self.get(&flow.from)?; @@ -76,7 +76,7 @@ impl AccountStore { pub fn flow_covered_until(&self, flow: &Flow) -> Result { let account = self.get(&flow.from)?; let deposit_cere = account.deposit.peek(); - let deposit_usd = self.1.to_usd(deposit_cere); + let deposit_usd = self.curr_converter.to_usd(deposit_cere); Ok(account.schedule_covered_until(deposit_usd)) } } diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index df95b355..dcd8e565 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -495,7 +495,7 @@ impl DdcBucket { let aggregate_payments_accounts; { - let conv = &self.accounts.1; + let conv = &self.accounts.curr_converter; aggregate_payments_accounts = aggregates_accounts.iter().map(|(client_id, resources_used)| { let account_id = *client_id; let cere_payment: Balance = conv.to_cere(*resources_used as Balance * cluster.cdn_usd_per_gb / KB_PER_GB ); @@ -513,7 +513,7 @@ impl DdcBucket { } }; - let conv = &self.accounts.1; + let conv = &self.accounts.curr_converter; let committer = &mut self.committer_store; for &(cdn_node_key, resources_used) in aggregates_nodes.iter() { diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 5807a868..666d03fb 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -1517,7 +1517,7 @@ fn cluster_distribute_cdn_revenue_ok() { let usd_per_kb = rate / KB_PER_GB; println!("The current rate per kb {}", usd_per_kb); - let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); + let cere_per_kb = ctx.contract.accounts.curr_converter.to_cere(usd_per_kb); println!("The current cere rate per kb {}", cere_per_kb); set_caller_value(ctx.provider_id0, 10 * TOKEN); diff --git a/bucket/ddc_bucket/tests/test_currency.rs b/bucket/ddc_bucket/tests/test_currency.rs index 9bb32b27..382625af 100644 --- a/bucket/ddc_bucket/tests/test_currency.rs +++ b/bucket/ddc_bucket/tests/test_currency.rs @@ -72,6 +72,6 @@ fn converter_ok() { let usd_per_kb = rate / KB_PER_GB; println!("The current rate per kb {}", usd_per_kb); - let cere_per_kb = ctx.contract.accounts.1.to_cere(usd_per_kb); + let cere_per_kb = ctx.contract.accounts.curr_converter.to_cere(usd_per_kb); println!("The current cere rate per kb {}", cere_per_kb); } From a451c521127bac399baa643c21a9607c2beafe4e Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 14:28:23 +0200 Subject: [PATCH 64/89] chore(perms): permissions store adapted to upgrades --- bucket/ddc_bucket/perm/store.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/bucket/ddc_bucket/perm/store.rs b/bucket/ddc_bucket/perm/store.rs index 32772d99..4d5a12e5 100644 --- a/bucket/ddc_bucket/perm/store.rs +++ b/bucket/ddc_bucket/perm/store.rs @@ -16,28 +16,29 @@ type PermKey = Vec; #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] -pub struct PermStore(pub Mapping); -// TODO: Switch to Mapping (must upgrade ink first). +pub struct PermStore { + pub perms: Mapping +} impl PermStore { pub fn grant_permission(&mut self, account_id: AccountId, permission: &Permission) { let key = (account_id, permission).encode(); - self.0.insert(key, &true); + self.perms.insert(key, &true); } pub fn revoke_permission(&mut self, account_id: AccountId, permission: &Permission) { let key = (account_id, permission).encode(); - self.0.remove(&key); + self.perms.remove(&key); } pub fn has_permission(&self, account_id: AccountId, permission: Permission) -> bool { let key = (account_id, permission).encode(); - if self.0.contains(&key) { + if self.perms.contains(&key) { return true; } let admin_key = (account_id, Permission::SuperAdmin).encode(); - self.0.contains(&admin_key) + self.perms.contains(&admin_key) } } From 0b823644fcd5d88942ededfdb04cd8a4348b4e5d Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 14:43:48 +0200 Subject: [PATCH 65/89] chore(lib): checking for unused variables --- bucket/ddc_bucket/tests/test_cdn_node.rs | 12 ++--- bucket/ddc_bucket/tests/test_cluster.rs | 63 ++++++++++++------------ bucket/ddc_bucket/tests/test_node.rs | 5 +- bucket/lib.rs | 2 +- 4 files changed, 40 insertions(+), 42 deletions(-) diff --git a/bucket/ddc_bucket/tests/test_cdn_node.rs b/bucket/ddc_bucket/tests/test_cdn_node.rs index 668fe757..b37c47ef 100644 --- a/bucket/ddc_bucket/tests/test_cdn_node.rs +++ b/bucket/ddc_bucket/tests/test_cdn_node.rs @@ -30,8 +30,6 @@ fn cdn_node_create_ok() { let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); let new_cdn_node_params = CdnNodeParams::from("{\"url\":\"https://ddc-1.cere.network/cdn/new\"}"); - let new_cdn_node_capacity = 100; - let new_cdn_node_rent_per_month: Balance = 10 * TOKEN; set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); ctx.contract.cdn_node_create( @@ -50,13 +48,14 @@ fn cdn_node_create_ok() { ); let cdn_node_info = ctx.contract.cdn_node_get(new_cdn_node_key)?; - assert!(matches!(cdn_node_info.cdn_node, CdnNode { + let _expected_cdn_node = CdnNode { provider_id: new_provider_id, undistributed_payment: 0, - cdn_node_params, + cdn_node_params: new_cdn_node_params, cluster_id: None, status_in_cluster: None, - })); + }; + assert!(matches!(cdn_node_info.cdn_node, _expected_cdn_node)); } @@ -170,7 +169,6 @@ fn cdn_node_get_err_if_node_does_not_exist() { fn node_get_ok() { let ctx = setup_cluster(); - let v_nodes1_len : u32 = ctx.v_nodes1.len().try_into().unwrap(); assert_eq!( ctx.contract.cdn_node_get(ctx.cdn_node_key1), Ok({ @@ -196,7 +194,6 @@ fn node_list_ok() { let cdn_node_info = ctx.contract.cdn_node_get(ctx.cdn_node_key1)?; assert_eq!(ctx.provider_id1, cdn_node_info.cdn_node.provider_id.clone()); - let v_nodes1_len : u32 = ctx.v_nodes1.len().try_into().unwrap(); let cdn_node1 = CdnNodeInfo { cdn_node_key: ctx.cdn_node_key1, cdn_node: CdnNode { @@ -208,7 +205,6 @@ fn node_list_ok() { }, }; - let v_nodes2_len : u32 = ctx.v_nodes2.len().try_into().unwrap(); let cdn_node2 = CdnNodeInfo { cdn_node_key: ctx.cdn_node_key2, cdn_node: CdnNode { diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 666d03fb..fd3ac81c 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -400,14 +400,14 @@ fn cluster_add_node_ok() { }) ); - let nodes_keys = vec![ + let _nodes_keys = vec![ ctx.node_key0, ctx.node_key1, ctx.node_key2, new_node_key, ]; - let cluster_v_nodes = vec![ + let _cluster_v_nodes = vec![ ctx.v_nodes0, ctx.v_nodes1, ctx.v_nodes2, @@ -416,11 +416,11 @@ fn cluster_add_node_ok() { let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; cluster_info.cluster_v_nodes.sort(); - assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); - assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); + assert!(matches!(cluster_info.cluster.nodes_keys, _nodes_keys)); + assert!(matches!(cluster_info.cluster_v_nodes, _cluster_v_nodes)); let node_info = ctx.contract.node_get(new_node_key)?; - let expected_node_info = NodeInfo { + let _expected_node_info = NodeInfo { node_key: new_node_key, node: Node { provider_id: new_provider_id, @@ -432,7 +432,7 @@ fn cluster_add_node_ok() { }, v_nodes: new_v_nodes }; - assert!(matches!(node_info, expected_node_info)); + assert!(matches!(node_info, _expected_node_info)); } @@ -500,23 +500,23 @@ fn cluster_remove_node_ok_if_node_provider() { }) ); - let nodes_keys = vec![ + let _nodes_keys = vec![ ctx.node_key0, ctx.node_key2, ]; - let cluster_v_nodes = vec![ + let _cluster_v_nodes = vec![ ctx.v_nodes0, ctx.v_nodes2, ]; let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; cluster_info.cluster_v_nodes.sort(); - assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); - assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); + assert!(matches!(cluster_info.cluster.nodes_keys, _nodes_keys)); + assert!(matches!(cluster_info.cluster_v_nodes, _cluster_v_nodes)); let node_info = ctx.contract.node_get(ctx.node_key1)?; - let expected_node_info = NodeInfo { + let _expected_node_info = NodeInfo { node_key: ctx.node_key1, node: Node { provider_id: ctx.provider_id1, @@ -528,7 +528,7 @@ fn cluster_remove_node_ok_if_node_provider() { }, v_nodes: Vec::new() }; - assert!(matches!(node_info, expected_node_info)); + assert!(matches!(node_info, _expected_node_info)); } @@ -551,23 +551,24 @@ fn cluster_remove_node_ok_if_cluster_manager() { }) ); - let nodes_keys = vec![ + let _nodes_keys = vec![ ctx.node_key0, ctx.node_key1, ]; - let cluster_v_nodes = vec![ + let _cluster_v_nodes = vec![ ctx.v_nodes0, ctx.v_nodes1, ]; let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; cluster_info.cluster_v_nodes.sort(); - assert!(matches!(cluster_info.cluster.nodes_keys, nodes_keys)); - assert!(matches!(cluster_info.cluster_v_nodes, cluster_v_nodes)); + assert!(matches!(cluster_info.cluster.nodes_keys, _nodes_keys)); + assert!(matches!(cluster_info.cluster_v_nodes, _cluster_v_nodes + )); let node_info = ctx.contract.node_get(ctx.node_key2)?; - let expected_node_info = NodeInfo { + let _expected_node_info = NodeInfo { node_key: ctx.node_key2, node: Node { provider_id: ctx.provider_id2, @@ -579,7 +580,7 @@ fn cluster_remove_node_ok_if_cluster_manager() { }, v_nodes: Vec::new() }; - assert!(matches!(node_info, expected_node_info)); + assert!(matches!(node_info, _expected_node_info)); } @@ -620,7 +621,7 @@ fn cluster_add_cdn_node_err_if_not_trusted_manager() { let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - let new_node_key = ctx.contract.cdn_node_create( + ctx.contract.cdn_node_create( new_cdn_node_key, CdnNodeParams::from("new_cdn_node"), )?; @@ -727,7 +728,7 @@ fn cluster_add_cdn_node_ok() { }) ); - let cdn_nodes_keys = vec![ + let _cdn_nodes_keys = vec![ ctx.cdn_node_key0, ctx.cdn_node_key1, ctx.cdn_node_key2, @@ -735,10 +736,10 @@ fn cluster_add_cdn_node_ok() { ]; let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; - assert!(matches!(cluster_info.cluster.cdn_nodes_keys, cdn_nodes_keys)); + assert!(matches!(cluster_info.cluster.cdn_nodes_keys, _cdn_nodes_keys)); let cdn_node_info = ctx.contract.cdn_node_get(new_cdn_node_key)?; - let expected_cdn_node_info = CdnNodeInfo { + let _expected_cdn_node_info = CdnNodeInfo { cdn_node_key: new_cdn_node_key, cdn_node: CdnNode { provider_id: new_provider_id, @@ -748,7 +749,7 @@ fn cluster_add_cdn_node_ok() { status_in_cluster: Some(NodeStatusInCluster::ADDING) }, }; - assert!(matches!(cdn_node_info, expected_cdn_node_info)); + assert!(matches!(cdn_node_info, _expected_cdn_node_info)); } @@ -814,16 +815,16 @@ fn cluster_remove_cdn_node_ok_if_cdn_node_provider() { }) ); - let cdn_nodes_keys = vec![ + let _cdn_nodes_keys = vec![ ctx.cdn_node_key0, ctx.cdn_node_key2, ]; let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; - assert!(matches!(cluster_info.cluster.cdn_nodes_keys, cdn_nodes_keys)); + assert!(matches!(cluster_info.cluster.cdn_nodes_keys, _cdn_nodes_keys)); let cdn_node_info = ctx.contract.cdn_node_get(ctx.cdn_node_key1)?; - let expected_cdn_node_info = CdnNodeInfo { + let _expected_cdn_node_info = CdnNodeInfo { cdn_node_key: ctx.cdn_node_key1, cdn_node: CdnNode { provider_id: ctx.provider_id1, @@ -833,7 +834,7 @@ fn cluster_remove_cdn_node_ok_if_cdn_node_provider() { status_in_cluster: None }, }; - assert!(matches!(cdn_node_info, expected_cdn_node_info)); + assert!(matches!(cdn_node_info, _expected_cdn_node_info)); } @@ -856,16 +857,16 @@ fn cluster_remove_cdn_node_ok_if_cluster_manager() { }) ); - let cdn_nodes_keys = vec![ + let _cdn_nodes_keys = vec![ ctx.cdn_node_key0, ctx.cdn_node_key1, ]; let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; - assert!(matches!(cluster_info.cluster.cdn_nodes_keys, cdn_nodes_keys)); + assert!(matches!(cluster_info.cluster.cdn_nodes_keys, _cdn_nodes_keys)); let cdn_node_info = ctx.contract.cdn_node_get(ctx.cdn_node_key2)?; - let expected_cdn_node_info = CdnNodeInfo { + let _expected_cdn_node_info = CdnNodeInfo { cdn_node_key: ctx.cdn_node_key2, cdn_node: CdnNode { provider_id: ctx.provider_id2, @@ -875,7 +876,7 @@ fn cluster_remove_cdn_node_ok_if_cluster_manager() { status_in_cluster: None }, }; - assert!(matches!(cdn_node_info, expected_cdn_node_info)); + assert!(matches!(cdn_node_info, _expected_cdn_node_info)); } diff --git a/bucket/ddc_bucket/tests/test_node.rs b/bucket/ddc_bucket/tests/test_node.rs index 5447e2a0..0ff9493b 100644 --- a/bucket/ddc_bucket/tests/test_node.rs +++ b/bucket/ddc_bucket/tests/test_node.rs @@ -52,14 +52,15 @@ fn node_create_ok() { ); let node_info = ctx.contract.node_get(new_node_key)?; - assert!(matches!(node_info.node, Node { + let _expected_node_info = Node { provider_id: new_provider_id, rent_per_month: new_node_rent_per_month, free_resource: new_node_capacity, node_params: new_node_params, cluster_id: None, status_in_cluster: None, - })); + }; + assert!(matches!(node_info.node, _expected_node_info)); } diff --git a/bucket/lib.rs b/bucket/lib.rs index eea904da..e3ac26e3 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -2,7 +2,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![feature(proc_macro_hygiene)] // for tests in a separate file -// #![deny(unused_must_use, unused_variables)] +#![deny(unused_must_use, unused_variables)] use ink_lang as ink; From 8779ef5ffeba727f6640b3e61e6f7b61e93004dc Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 15:07:13 +0200 Subject: [PATCH 66/89] chore(perms): permissions store is moved to top index --- bucket/ddc_bucket/perm/messages.rs | 4 ++-- bucket/ddc_bucket/perm/store.rs | 4 ++-- bucket/lib.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/bucket/ddc_bucket/perm/messages.rs b/bucket/ddc_bucket/perm/messages.rs index caed1e79..9c34759f 100644 --- a/bucket/ddc_bucket/perm/messages.rs +++ b/bucket/ddc_bucket/perm/messages.rs @@ -8,12 +8,12 @@ use crate::ddc_bucket::perm::entity::Permission; impl DdcBucket { pub fn grant_permission(&mut self, account_id: AccountId, permission: Permission) -> Result<()> { - self.perms.grant_permission(account_id, &permission); + self.perms.grant_permission(account_id, permission); Ok(()) } pub fn revoke_permission(&mut self, account_id: AccountId, permission: Permission) -> Result<()> { - self.perms.revoke_permission(account_id, &permission); + self.perms.revoke_permission(account_id, permission); Ok(()) } diff --git a/bucket/ddc_bucket/perm/store.rs b/bucket/ddc_bucket/perm/store.rs index 4d5a12e5..deabc3fb 100644 --- a/bucket/ddc_bucket/perm/store.rs +++ b/bucket/ddc_bucket/perm/store.rs @@ -22,12 +22,12 @@ pub struct PermStore { impl PermStore { - pub fn grant_permission(&mut self, account_id: AccountId, permission: &Permission) { + pub fn grant_permission(&mut self, account_id: AccountId, permission: Permission) { let key = (account_id, permission).encode(); self.perms.insert(key, &true); } - pub fn revoke_permission(&mut self, account_id: AccountId, permission: &Permission) { + pub fn revoke_permission(&mut self, account_id: AccountId, permission: Permission) { let key = (account_id, permission).encode(); self.perms.remove(&key); } diff --git a/bucket/lib.rs b/bucket/lib.rs index e3ac26e3..fc4f308a 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -51,12 +51,12 @@ pub mod ddc_bucket { #[ink(storage)] #[derive(SpreadAllocate, Default)] pub struct DdcBucket { + perms: PermStore, buckets: BucketStore, clusters: ClusterStore, cdn_nodes: CdnNodeStore, nodes: NodeStore, accounts: AccountStore, - perms: PermStore, network_fee: NetworkFeeStore, committer_store: CommitterStore, protocol_store: ProtocolStore, @@ -72,7 +72,7 @@ pub mod ddc_bucket { ink_lang::utils::initialize_contract(|contract: &mut Self| { let admin = Self::env().caller(); // Make the creator of this contract a super-admin. - contract.perms.grant_permission(admin, &Permission::SuperAdmin); + contract.perms.grant_permission(admin, Permission::SuperAdmin); contract.committer_store.init(admin); contract.protocol_store.init(admin, DEFAULT_BASIS_POINTS); }) From 71b096ce59fc410e94eefbaa7c6d2708ac5e6e64 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 16:03:23 +0200 Subject: [PATCH 67/89] fix(accounts): currency converter is fixed --- bucket/ddc_bucket/currency.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/bucket/ddc_bucket/currency.rs b/bucket/ddc_bucket/currency.rs index 713a39d5..384d07d4 100644 --- a/bucket/ddc_bucket/currency.rs +++ b/bucket/ddc_bucket/currency.rs @@ -8,35 +8,42 @@ use crate::ddc_bucket::{Balance, TOKEN}; pub type CERE = Balance; pub type USD = Balance; +const PRECISION: Balance = 10_000_000; #[derive(SpreadLayout)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] -pub struct CurrencyConverter(Balance /* how many USD for PRECISION CERE */); +pub struct CurrencyConverter { + /* how many USD for PRECISION CERE */ + rate: Balance +} -const PRECISION: Balance = 10_000_000; impl SpreadAllocate for CurrencyConverter { fn allocate_spread(_: &mut KeyPtr) -> Self { - Self(PRECISION) + Self { + rate: PRECISION + } } } impl Default for CurrencyConverter { fn default() -> Self { - Self(PRECISION) + Self { + rate: PRECISION + } } } impl CurrencyConverter { // 10_000_000 pub fn set_usd_per_cere(&mut self, usd_per_cere: USD) { - self.0 = usd_per_cere * PRECISION / TOKEN; + self.rate = usd_per_cere * PRECISION / TOKEN; } pub fn to_cere(&self, usd: USD) -> CERE { - usd * PRECISION / self.0 + usd * PRECISION / self.rate } pub fn to_usd(&self, cere: CERE) -> USD { - self.0 * cere / PRECISION + self.rate * cere / PRECISION } } From 7a6b85a6b596be0a1e1b97543333947c753a2e52 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 16:30:58 +0200 Subject: [PATCH 68/89] fix(account): currency converter default initialization is fixed --- bucket/ddc_bucket/currency.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/bucket/ddc_bucket/currency.rs b/bucket/ddc_bucket/currency.rs index 384d07d4..4cf0a16b 100644 --- a/bucket/ddc_bucket/currency.rs +++ b/bucket/ddc_bucket/currency.rs @@ -1,16 +1,16 @@ //! The privileged interface for admin tasks. -use ink_storage::traits::{SpreadAllocate, SpreadLayout}; -use ink_storage::traits::KeyPtr; - +use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout}; +use scale::{Decode, Encode}; use crate::ddc_bucket::{Balance, TOKEN}; + pub type CERE = Balance; pub type USD = Balance; const PRECISION: Balance = 10_000_000; -#[derive(SpreadLayout)] +#[derive(Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct CurrencyConverter { /* how many USD for PRECISION CERE */ @@ -18,14 +18,6 @@ pub struct CurrencyConverter { } -impl SpreadAllocate for CurrencyConverter { - fn allocate_spread(_: &mut KeyPtr) -> Self { - Self { - rate: PRECISION - } - } -} - impl Default for CurrencyConverter { fn default() -> Self { Self { From bf045afd782941a0bff34c1227457ddfc5326705 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 18:07:58 +0200 Subject: [PATCH 69/89] fix(constructor): spread allocate trait impl is replaced with default impl to fix storage initialization --- bucket/ddc_bucket/account/messages.rs | 10 +++---- bucket/ddc_bucket/account/store.rs | 12 ++++----- bucket/ddc_bucket/bucket/messages.rs | 4 +-- bucket/ddc_bucket/cash.rs | 14 +--------- bucket/ddc_bucket/cdn_node/entity.rs | 1 - bucket/ddc_bucket/cluster/messages.rs | 34 ++++++++++++------------ bucket/ddc_bucket/committer/messages.rs | 14 +++++----- bucket/ddc_bucket/currency.rs | 19 +++++-------- bucket/ddc_bucket/network_fee.rs | 13 +++++---- bucket/ddc_bucket/node/entity.rs | 2 +- bucket/ddc_bucket/node/messages.rs | 4 +-- bucket/ddc_bucket/protocol/messages.rs | 14 +++++----- bucket/ddc_bucket/protocol/store.rs | 7 +++-- bucket/ddc_bucket/tests/test_cluster.rs | 2 +- bucket/ddc_bucket/tests/test_currency.rs | 2 +- bucket/ddc_bucket/topology/messages.rs | 6 ++--- bucket/lib.rs | 13 ++++----- scripts/sdk/src/abi/ddc_bucket.json | 6 ++--- 18 files changed, 82 insertions(+), 95 deletions(-) diff --git a/bucket/ddc_bucket/account/messages.rs b/bucket/ddc_bucket/account/messages.rs index 87a202f8..c18ff5a5 100644 --- a/bucket/ddc_bucket/account/messages.rs +++ b/bucket/ddc_bucket/account/messages.rs @@ -36,7 +36,7 @@ impl DdcBucket { let account_id = Self::env().caller(); if let Ok(mut account) = self.accounts.get(&account_id) { - let conv = &self.accounts.curr_converter; + let conv = &self.protocol.curr_converter; account.bond(time_ms, conv, bond_amount)?; self.accounts.save(&account_id, &account); Ok(()) @@ -68,12 +68,12 @@ impl DdcBucket { } pub fn message_account_get_usd_per_cere(&self) -> Balance { - self.accounts.curr_converter.to_usd(1 * TOKEN) + self.protocol.curr_converter.to_usd(1 * TOKEN) } pub fn message_account_set_usd_per_cere(&mut self, usd_per_cere: Balance) { self.only_with_permission(Permission::SetExchangeRate).unwrap(); - self.accounts.curr_converter.set_usd_per_cere(usd_per_cere) + self.protocol.curr_converter.set_usd_per_cere(usd_per_cere) } pub fn receive_cash() -> Cash { @@ -91,7 +91,7 @@ impl DdcBucket { fn _account_withdraw(&mut self, from: AccountId, payable: Payable) -> Result<()> { if let Ok(mut account) = self.accounts.get(&from) { let time_ms = Self::env().block_timestamp(); - let conv = &self.accounts.curr_converter; + let conv = &self.protocol.curr_converter; account.withdraw(time_ms, conv, payable)?; self.accounts.save(&from, &account); Ok(()) @@ -115,7 +115,7 @@ impl DdcBucket { None => 0, Some(account) => { let time_ms = Self::env().block_timestamp(); - let conv = &self.accounts.curr_converter; + let conv = &self.protocol.curr_converter; account.get_withdrawable(time_ms, conv) } } diff --git a/bucket/ddc_bucket/account/store.rs b/bucket/ddc_bucket/account/store.rs index bf23ab86..050bb134 100644 --- a/bucket/ddc_bucket/account/store.rs +++ b/bucket/ddc_bucket/account/store.rs @@ -1,13 +1,12 @@ //! The store to create and access Accounts. use ink_storage::Mapping; - use crate::ddc_bucket::{ AccountId, Balance, cash::Cash, Error::*, Result, schedule::Schedule, + currency::CurrencyConverter }; -use crate::ddc_bucket::currency::CurrencyConverter; use crate::ddc_bucket::flow::Flow; use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_prelude::vec::Vec; @@ -19,7 +18,6 @@ pub struct AccountStore { pub accounts: Mapping, // todo: remove this vector as it can store an arbitrary number of elements and easily exceed 16KB limit pub accounts_keys: Vec, - pub curr_converter: CurrencyConverter, } impl AccountStore { @@ -61,9 +59,9 @@ impl AccountStore { Ok(()) } - pub fn settle_flow(&mut self, now_ms: u64, flow: &mut Flow) -> Result { + pub fn settle_flow(&mut self, now_ms: u64, flow: &mut Flow, curr_converter: &CurrencyConverter) -> Result { let flowed_usd = flow.schedule.take_value_at_time(now_ms); - let flowed_cere = self.curr_converter.to_cere(flowed_usd); + let flowed_cere = curr_converter.to_cere(flowed_usd); let (payable, cash) = Cash::borrow_payable_cash(flowed_cere); let mut account = self.get(&flow.from)?; @@ -73,10 +71,10 @@ impl AccountStore { Ok(cash) } - pub fn flow_covered_until(&self, flow: &Flow) -> Result { + pub fn flow_covered_until(&self, flow: &Flow, curr_converter: &CurrencyConverter) -> Result { let account = self.get(&flow.from)?; let deposit_cere = account.deposit.peek(); - let deposit_usd = self.curr_converter.to_usd(deposit_cere); + let deposit_usd = curr_converter.to_usd(deposit_cere); Ok(account.schedule_covered_until(deposit_usd)) } } diff --git a/bucket/ddc_bucket/bucket/messages.rs b/bucket/ddc_bucket/bucket/messages.rs index 0a55f498..1ddf397f 100644 --- a/bucket/ddc_bucket/bucket/messages.rs +++ b/bucket/ddc_bucket/bucket/messages.rs @@ -51,7 +51,7 @@ impl DdcBucket { let mut bucket = self.buckets.get(bucket_id)?; let now_ms = Self::env().block_timestamp(); - let cash = self.accounts.settle_flow(now_ms, &mut bucket.flow)?; + let cash = self.accounts.settle_flow(now_ms, &mut bucket.flow, &self.protocol.curr_converter)?; let mut cluster = self.clusters.get(bucket.cluster_id)?; cluster.revenues.increase(cash); @@ -118,7 +118,7 @@ impl DdcBucket { pub fn bucket_calculate_status(&self, bucket_id: BucketId, bucket: Bucket) -> Result { let mut writer_ids = self.buckets.get_bucket_readers(bucket_id); writer_ids.push(bucket.owner_id); - let rent_covered_until_ms = self.accounts.flow_covered_until(&bucket.flow)?; + let rent_covered_until_ms = self.accounts.flow_covered_until(&bucket.flow, &self.protocol.curr_converter)?; let reader_ids = self.buckets.get_bucket_readers(bucket_id); let bucket_params = bucket.bucket_params.clone(); diff --git a/bucket/ddc_bucket/cash.rs b/bucket/ddc_bucket/cash.rs index 20766771..d427c23f 100644 --- a/bucket/ddc_bucket/cash.rs +++ b/bucket/ddc_bucket/cash.rs @@ -3,7 +3,6 @@ //! These data structures facilitate the correctness of money-related calculations using the Rust type system. use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout}; -use ink_storage::traits::KeyPtr; use scale::{Decode, Encode}; use crate::ddc_bucket::{Balance, Result}; @@ -12,21 +11,10 @@ use crate::ddc_bucket::Error::InsufficientBalance; // TODO: remove Clone. /// Cash represents some value that was taken from someone, and that must be credited to someone. #[must_use] -#[derive(Clone, Copy, PartialEq, Encode, Decode, SpreadLayout, PackedLayout)] +#[derive(Default, Clone, Copy, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct Cash(pub Balance); -impl SpreadAllocate for Cash { - fn allocate_spread(_: &mut KeyPtr) -> Self { - Self(0) - } -} - -impl Default for Cash { - fn default() -> Self { - Self(0) - } -} /// Payable represents some value that was credited to someone, and that must be paid by someone. /// Payable must be covered by Cash at all times to guarantee the balance of the contract. diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index 7593f2d4..1b927718 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -10,7 +10,6 @@ use ink_prelude::string::String; pub type ProviderId = AccountId; pub type CdnNodeKey = AccountId; pub type CdnNodeParams = String; -pub type Resource = u32; #[derive(Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index dcd8e565..3436e7ea 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -33,7 +33,7 @@ impl DdcBucket { cluster_params.clone() )?; - self.topology_store.create_topology(cluster_id)?; + self.topology.create_topology(cluster_id)?; Self::env().emit_event(ClusterCreated { cluster_id, @@ -69,7 +69,7 @@ impl DdcBucket { } self.clusters.update(cluster_id, &cluster)?; - self.topology_store.add_node(cluster_id, node_key, v_nodes)?; + self.topology.add_node(cluster_id, node_key, v_nodes)?; Self::env().emit_event(ClusterNodeAdded { cluster_id, @@ -101,13 +101,13 @@ impl DdcBucket { self.nodes.update(node_key, &node)?; cluster.remove_node(node_key); - let v_nodes = self.topology_store.get_v_nodes_by_node(node_key); + let v_nodes = self.topology.get_v_nodes_by_node(node_key); for _v_node in &v_nodes { cluster.total_rent -= node.rent_per_month; } self.clusters.update(cluster_id, &cluster)?; - self.topology_store.remove_node(cluster_id, node_key)?; + self.topology.remove_node(cluster_id, node_key)?; Self::env().emit_event(ClusterNodeRemoved { cluster_id, @@ -130,7 +130,7 @@ impl DdcBucket { // Give back resources to the old node for all its v_nodes for v_node in &v_nodes { - let old_node_key = self.topology_store.get_node_by_v_node(cluster_id, *v_node)?; + let old_node_key = self.topology.get_node_by_v_node(cluster_id, *v_node)?; // Give back resources to the old node let mut old_node = self.nodes.get(old_node_key)?; @@ -146,7 +146,7 @@ impl DdcBucket { self.nodes.update(new_node_key, &new_node)?; } - self.topology_store + self.topology .replace_node(cluster_id, new_node_key, v_nodes)?; Self::env().emit_event(ClusterNodeReplaced { @@ -230,7 +230,7 @@ impl DdcBucket { cluster.only_without_nodes()?; self.clusters.remove(cluster_id); - self.topology_store.remove_topology(cluster_id)?; + self.topology.remove_topology(cluster_id)?; Self::env().emit_event(ClusterRemoved { cluster_id, @@ -355,9 +355,9 @@ impl DdcBucket { cluster.put_resource(resource); self.clusters.update(cluster_id, &cluster)?; - let cluster_v_nodes = self.topology_store.get_v_nodes_by_cluster(cluster_id); + let cluster_v_nodes = self.topology.get_v_nodes_by_cluster(cluster_id); for v_node in cluster_v_nodes { - let node_key = self.topology_store.get_node_by_v_node(cluster_id, v_node)?; + let node_key = self.topology.get_node_by_v_node(cluster_id, v_node)?; let mut node = self.nodes.get(node_key)?; node.take_resource(resource)?; self.nodes.update(node_key, &node)?; @@ -373,7 +373,7 @@ impl DdcBucket { pub fn message_cluster_get(&self, cluster_id: ClusterId) -> Result { let cluster = self.clusters.get(cluster_id)?; - let cluster_v_nodes = self.topology_store.get_v_nodes_by_cluster(cluster_id); + let cluster_v_nodes = self.topology.get_v_nodes_by_cluster(cluster_id); Ok(ClusterInfo { cluster_id, @@ -402,7 +402,7 @@ impl DdcBucket { } } - let cluster_v_nodes = self.topology_store.get_v_nodes_by_cluster(cluster_id); + let cluster_v_nodes = self.topology.get_v_nodes_by_cluster(cluster_id); // Include the complete status of matched items. let cluster_info = ClusterInfo { @@ -495,7 +495,7 @@ impl DdcBucket { let aggregate_payments_accounts; { - let conv = &self.accounts.curr_converter; + let conv = &self.protocol.curr_converter; aggregate_payments_accounts = aggregates_accounts.iter().map(|(client_id, resources_used)| { let account_id = *client_id; let cere_payment: Balance = conv.to_cere(*resources_used as Balance * cluster.cdn_usd_per_gb / KB_PER_GB ); @@ -513,15 +513,15 @@ impl DdcBucket { } }; - let conv = &self.accounts.curr_converter; - let committer = &mut self.committer_store; + let conv = self.protocol.curr_converter.clone(); + let committer = &mut self.committer; for &(cdn_node_key, resources_used) in aggregates_nodes.iter() { let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; - let protocol_fee = self.protocol_store.get_fee_bp(); - let protocol = &mut self.protocol_store; + let protocol_fee = self.protocol.get_fee_bp(); + let protocol = &mut self.protocol; - let payment = conv.to_cere (resources_used as Balance * cluster.cdn_usd_per_gb / KB_PER_GB ); + let payment = conv.to_cere(resources_used as Balance * cluster.cdn_usd_per_gb / KB_PER_GB ); // let protocol_payment = payment * protocol_fee as u128/ 10_000; let node_payment = payment * (10_000 - protocol_fee) as u128 / 10_000; diff --git a/bucket/ddc_bucket/committer/messages.rs b/bucket/ddc_bucket/committer/messages.rs index 38ae02cc..bfbd5e86 100644 --- a/bucket/ddc_bucket/committer/messages.rs +++ b/bucket/ddc_bucket/committer/messages.rs @@ -8,22 +8,23 @@ use super::store::{Commit, EraConfig, EraStatus, EraAndTimestamp}; pub type Result = core::result::Result; impl DdcBucket { + pub fn message_set_commit(&mut self, cdn_owner: AccountId, cdn_node_key: CdnNodeKey, commit: Commit) { - self.committer_store.set_commit(cdn_owner, cdn_node_key, commit); + self.committer.set_commit(cdn_owner, cdn_node_key, commit); } pub fn message_get_commit(&self, cdn_owner: AccountId) -> Vec<(CdnNodeKey, Commit)> { - self.committer_store.get_commit(cdn_owner) + self.committer.get_commit(cdn_owner) } pub fn message_get_validated_commit(&self, cdn_node_key: CdnNodeKey) -> EraAndTimestamp { - self.committer_store.get_validate_commit(cdn_node_key) + self.committer.get_validate_commit(cdn_node_key) } pub fn message_set_era(&mut self, era_config: EraConfig) -> Result<()> { let caller = Self::env().caller(); - match self.committer_store.set_era(caller, era_config) { + match self.committer.set_era(caller, era_config) { Err(_e) => panic!("Setting era failed"), Ok(_v) => Ok(()), } @@ -31,10 +32,11 @@ impl DdcBucket { pub fn message_get_era(&self) -> EraStatus { let timestamp = Self::env().block_timestamp(); - self.committer_store.get_era(timestamp) + self.committer.get_era(timestamp) } pub fn message_get_era_settings(&self) -> EraConfig { - self.committer_store.get_era_settings() + self.committer.get_era_settings() } + } \ No newline at end of file diff --git a/bucket/ddc_bucket/currency.rs b/bucket/ddc_bucket/currency.rs index 4cf0a16b..0f285e8a 100644 --- a/bucket/ddc_bucket/currency.rs +++ b/bucket/ddc_bucket/currency.rs @@ -2,31 +2,26 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout}; use scale::{Decode, Encode}; -use crate::ddc_bucket::{Balance, TOKEN}; - +use crate::ddc_bucket::{Balance, TOKEN, PRECISION}; pub type CERE = Balance; pub type USD = Balance; -const PRECISION: Balance = 10_000_000; - -#[derive(Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] -#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] +#[derive(Default, Clone, PartialEq, Encode, Decode, SpreadAllocate, PackedLayout, SpreadLayout)] +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug, scale_info::TypeInfo))] pub struct CurrencyConverter { /* how many USD for PRECISION CERE */ rate: Balance } - -impl Default for CurrencyConverter { - fn default() -> Self { +impl CurrencyConverter { + + pub fn new(rate: Balance) -> Self { Self { - rate: PRECISION + rate } } -} -impl CurrencyConverter { // 10_000_000 pub fn set_usd_per_cere(&mut self, usd_per_cere: USD) { self.rate = usd_per_cere * PRECISION / TOKEN; } diff --git a/bucket/ddc_bucket/network_fee.rs b/bucket/ddc_bucket/network_fee.rs index 72de6a0c..25b277f1 100644 --- a/bucket/ddc_bucket/network_fee.rs +++ b/bucket/ddc_bucket/network_fee.rs @@ -13,13 +13,13 @@ const BP: BasisPoints = 10_000; // 100% #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] -pub struct NetworkFeeStore( - pub FeeConfig, -); +pub struct NetworkFeeStore { + pub fee_config: FeeConfig, +} impl NetworkFeeStore { pub fn cluster_management_fee_bp(&self) -> BasisPoints { - self.0.cluster_management_fee_bp + self.fee_config.cluster_management_fee_bp } } @@ -31,7 +31,6 @@ pub struct FeeConfig { pub network_fee_bp: BasisPoints, /// The destination account of network fees. Use the 0 account to burn the fees. pub network_fee_destination: AccountId, - /// The fee rate from cluster revenues to the cluster manager. In basis points (1% of 1%). pub cluster_management_fee_bp: BasisPoints, } @@ -40,7 +39,7 @@ pub struct FeeConfig { impl DdcBucket { /// Take a network fee from the given revenues (in place). pub fn capture_network_fee(store: &NetworkFeeStore, revenues: &mut Cash) -> Result<()> { - let config = &store.0; + let config = &store.fee_config; Self::capture_fee(config.network_fee_bp, config.network_fee_destination, revenues) } @@ -54,7 +53,7 @@ impl DdcBucket { pub fn message_admin_set_fee_config(&mut self, config: FeeConfig) -> Result<()> { self.only_with_permission(Permission::SuperAdmin)?; - self.network_fee.0 = config; + self.network_fee.fee_config = config; Ok(()) } } diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index 0ff3715e..b0503c83 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -38,8 +38,8 @@ impl ink_storage::traits::PackedAllocate for Node { #[derive(Clone, PartialEq, Encode, Decode, SpreadLayout, PackedLayout)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] pub enum NodeStatusInCluster { - ACTIVE, ADDING, + ACTIVE, DELETING, OFFLINE, } diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index 9708f5c5..460324de 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -77,7 +77,7 @@ impl DdcBucket { pub fn message_node_get(&self, node_key: NodeKey) -> Result { let node = self.nodes.get(node_key)?; - let v_nodes = self.topology_store.get_v_nodes_by_node(node_key); + let v_nodes = self.topology.get_v_nodes_by_node(node_key); Ok(NodeInfo { node_key, @@ -108,7 +108,7 @@ impl DdcBucket { } } - let v_nodes = self.topology_store.get_v_nodes_by_node(node_key); + let v_nodes = self.topology.get_v_nodes_by_node(node_key); // Include the complete status of matched items. let node_info = NodeInfo { diff --git a/bucket/ddc_bucket/protocol/messages.rs b/bucket/ddc_bucket/protocol/messages.rs index 88007687..042f3376 100644 --- a/bucket/ddc_bucket/protocol/messages.rs +++ b/bucket/ddc_bucket/protocol/messages.rs @@ -4,32 +4,34 @@ use crate::ddc_bucket::{DdcBucket, Result}; use crate::ddc_bucket::cash::{Cash, Payable}; impl DdcBucket { + pub fn message_get_fee_bp(&self) -> u32 { - self.protocol_store.get_fee_bp() + self.protocol.get_fee_bp() } pub fn message_set_fee_bp(&mut self, fee_bp: u32) -> Result<()> { - match self.protocol_store.set_fee_bp(fee_bp) { + match self.protocol.set_fee_bp(fee_bp) { Err(_e) => panic!("Setting fee failed"), Ok(_v) => Ok(()), } } pub fn message_get_fee_revenues(&self) -> Cash { - self.protocol_store.get_fee_revenues() + self.protocol.get_fee_revenues() } pub fn message_put_fee_revenues(&mut self, amount: Cash) -> Result<()> { - self.protocol_store.put_revenues(amount); + self.protocol.put_revenues(amount); Ok(()) } pub fn message_withdraw_revenues(&mut self, amount: u128) -> Result<()> { - self.protocol_store.withdraw_revenues(Payable(amount))?; + self.protocol.withdraw_revenues(Payable(amount))?; - Self::send_cash(self.protocol_store.admin, Cash(amount))?; + Self::send_cash(self.protocol.admin, Cash(amount))?; Ok(()) } + } \ No newline at end of file diff --git a/bucket/ddc_bucket/protocol/store.rs b/bucket/ddc_bucket/protocol/store.rs index 94d42fdd..dd2f598d 100644 --- a/bucket/ddc_bucket/protocol/store.rs +++ b/bucket/ddc_bucket/protocol/store.rs @@ -2,8 +2,9 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout}; use scale::{Decode, Encode}; -use crate::ddc_bucket::{AccountId, Error::*, Result}; +use crate::ddc_bucket::{AccountId, Error::*, Result, PRECISION}; use crate::ddc_bucket::cash::{Cash, Payable}; +use crate::ddc_bucket::currency::CurrencyConverter; #[derive(Default, Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug, scale_info::TypeInfo))] @@ -11,13 +12,15 @@ pub struct ProtocolStore { pub admin: AccountId, pub fee_bp: u32, pub revenues: Cash, + pub curr_converter: CurrencyConverter, } impl ProtocolStore { pub fn init(&mut self, admin: AccountId, fee_bp: u32) { self.admin = admin; - self.fee_bp = fee_bp + self.fee_bp = fee_bp; + self.curr_converter = CurrencyConverter::new(PRECISION); } pub fn get_fee_bp(&self) -> u32 { diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index fd3ac81c..b8a9d333 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -1518,7 +1518,7 @@ fn cluster_distribute_cdn_revenue_ok() { let usd_per_kb = rate / KB_PER_GB; println!("The current rate per kb {}", usd_per_kb); - let cere_per_kb = ctx.contract.accounts.curr_converter.to_cere(usd_per_kb); + let cere_per_kb = ctx.contract.protocol.curr_converter.to_cere(usd_per_kb); println!("The current cere rate per kb {}", cere_per_kb); set_caller_value(ctx.provider_id0, 10 * TOKEN); diff --git a/bucket/ddc_bucket/tests/test_currency.rs b/bucket/ddc_bucket/tests/test_currency.rs index 382625af..3050f6f0 100644 --- a/bucket/ddc_bucket/tests/test_currency.rs +++ b/bucket/ddc_bucket/tests/test_currency.rs @@ -72,6 +72,6 @@ fn converter_ok() { let usd_per_kb = rate / KB_PER_GB; println!("The current rate per kb {}", usd_per_kb); - let cere_per_kb = ctx.contract.accounts.curr_converter.to_cere(usd_per_kb); + let cere_per_kb = ctx.contract.protocol.curr_converter.to_cere(usd_per_kb); println!("The current cere rate per kb {}", cere_per_kb); } diff --git a/bucket/ddc_bucket/topology/messages.rs b/bucket/ddc_bucket/topology/messages.rs index 9a714a62..51051404 100644 --- a/bucket/ddc_bucket/topology/messages.rs +++ b/bucket/ddc_bucket/topology/messages.rs @@ -7,15 +7,15 @@ use ink_prelude::vec::Vec; impl DdcBucket { pub fn message_get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Vec { - self.topology_store.get_v_nodes_by_cluster(cluster_id) + self.topology.get_v_nodes_by_cluster(cluster_id) } pub fn message_get_v_nodes_by_node(&self, node_key: NodeKey) -> Vec { - self.topology_store.get_v_nodes_by_node(node_key) + self.topology.get_v_nodes_by_node(node_key) } pub fn message_get_node_by_v_node(&self, cluster_id: ClusterId, v_node: VNodeToken) -> Result { - self.topology_store.get_node_by_v_node(cluster_id, v_node) + self.topology.get_node_by_v_node(cluster_id, v_node) } } \ No newline at end of file diff --git a/bucket/lib.rs b/bucket/lib.rs index fc4f308a..61886f1b 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -56,11 +56,11 @@ pub mod ddc_bucket { clusters: ClusterStore, cdn_nodes: CdnNodeStore, nodes: NodeStore, + topology: TopologyStore, accounts: AccountStore, network_fee: NetworkFeeStore, - committer_store: CommitterStore, - protocol_store: ProtocolStore, - topology_store: TopologyStore, + committer: CommitterStore, + protocol: ProtocolStore, } impl DdcBucket { @@ -72,9 +72,9 @@ pub mod ddc_bucket { ink_lang::utils::initialize_contract(|contract: &mut Self| { let admin = Self::env().caller(); // Make the creator of this contract a super-admin. - contract.perms.grant_permission(admin, Permission::SuperAdmin); - contract.committer_store.init(admin); - contract.protocol_store.init(admin, DEFAULT_BASIS_POINTS); + contract.perms.grant_permission(admin, Permission::SuperAdmin); + contract.committer.init(admin); + contract.protocol.init(admin, DEFAULT_BASIS_POINTS); }) } } @@ -1658,6 +1658,7 @@ pub mod ddc_bucket { /// One token with 10 decimals. pub const TOKEN: Balance = 10_000_000_000; pub const DEFAULT_BASIS_POINTS: u32 = 500; + pub const PRECISION: Balance = 10_000_000; #[derive(Debug, PartialEq, Eq, Encode, Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index f09ebb11..956a7ee5 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -3051,7 +3051,7 @@ ] } }, - "name": "committer_store" + "name": "committer" }, { "layout": { @@ -3096,7 +3096,7 @@ ] } }, - "name": "protocol_store" + "name": "protocol" }, { "layout": { @@ -3114,7 +3114,7 @@ ] } }, - "name": "topology_store" + "name": "topology" } ] } From d0ebdd5dbc782d246bf7cf216fb4e45f09f64dbb Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Thu, 29 Jun 2023 19:28:44 +0200 Subject: [PATCH 70/89] chore(lib): storage layout for fee configuration is merged with protocol to decrease the size --- bucket/ddc_bucket/cluster/messages.rs | 25 ++--- bucket/ddc_bucket/currency.rs | 10 +- bucket/ddc_bucket/network_fee.rs | 59 ------------ bucket/ddc_bucket/protocol/messages.rs | 22 ++--- bucket/ddc_bucket/protocol/store.rs | 116 +++++++++++++++++------- bucket/ddc_bucket/tests/test_cluster.rs | 13 +-- bucket/lib.rs | 47 +++++----- 7 files changed, 141 insertions(+), 151 deletions(-) delete mode 100644 bucket/ddc_bucket/network_fee.rs diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 3436e7ea..5b0f6ef3 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -11,9 +11,11 @@ use crate::ddc_bucket::topology::store::{VNodeToken}; use crate::ddc_bucket::perm::entity::Permission; use crate::ddc_bucket::ClusterNodeReplaced; use crate::ddc_bucket::{ + BASIS_POINTS, AccountId, Balance, ClusterCreated, ClusterNodeAdded, ClusterNodeRemoved, ClusterCdnNodeAdded, ClusterCdnNodeRemoved, ClusterDistributeRevenues, CdnClusterDistributeRevenues, ClusterReserveResource, - ClusterRemoved, ClusterParamsSet, ClusterNodeStatusSet, ClusterCdnNodeStatusSet, PermissionGranted, PermissionRevoked, DdcBucket, NodeStatusInCluster, Result, Error::* + ClusterRemoved, ClusterParamsSet, ClusterNodeStatusSet, ClusterCdnNodeStatusSet, PermissionGranted, PermissionRevoked, + DdcBucket, NodeStatusInCluster, Result, Error::* }; use super::entity::{ClusterId, ClusterParams}; @@ -421,11 +423,11 @@ impl DdcBucket { let mut cluster = self.clusters.get(cluster_id)?; // Charge the network fee from the cluster. - Self::capture_network_fee(&self.network_fee, &mut cluster.revenues)?; + self.capture_network_fee(&mut cluster.revenues)?; // Charge the cluster management fee. - Self::capture_fee( - self.network_fee.cluster_management_fee_bp(), + self.capture_fee( + self.protocol.cluster_management_fee_bp(), cluster.manager_id, &mut cluster.revenues, )?; @@ -518,13 +520,13 @@ impl DdcBucket { for &(cdn_node_key, resources_used) in aggregates_nodes.iter() { let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; - let protocol_fee = self.protocol.get_fee_bp(); + let protocol_fee = self.protocol.get_protocol_fee_bp(); let protocol = &mut self.protocol; let payment = conv.to_cere(resources_used as Balance * cluster.cdn_usd_per_gb / KB_PER_GB ); - // let protocol_payment = payment * protocol_fee as u128/ 10_000; - let node_payment = payment * (10_000 - protocol_fee) as u128 / 10_000; + // let protocol_payment = payment * protocol_fee as u128/ BASIS_POINTS; + let node_payment = payment * (BASIS_POINTS - protocol_fee) as u128 / BASIS_POINTS; let protocol_payment = payment - node_payment; cdn_node.put_payment(node_payment); @@ -559,13 +561,14 @@ impl DdcBucket { let mut cluster = self.clusters.get(cluster_id)?; // Charge the network fee from the cluster. - Self::capture_network_fee(&self.network_fee, &mut cluster.cdn_revenues)?; + self.capture_network_fee(&mut cluster.cdn_revenues)?; // Charge the cluster management fee. - Self::capture_fee( - self.network_fee.cluster_management_fee_bp(), + self.capture_fee( + self.protocol.cluster_management_fee_bp(), cluster.manager_id, - &mut cluster.cdn_revenues)?; + &mut cluster.cdn_revenues + )?; // First accumulated revenues to distribute. let mut distributed_revenue = 0; diff --git a/bucket/ddc_bucket/currency.rs b/bucket/ddc_bucket/currency.rs index 0f285e8a..51731d76 100644 --- a/bucket/ddc_bucket/currency.rs +++ b/bucket/ddc_bucket/currency.rs @@ -2,7 +2,9 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout}; use scale::{Decode, Encode}; -use crate::ddc_bucket::{Balance, TOKEN, PRECISION}; +use crate::ddc_bucket::{Balance, TOKEN}; + +pub const PRECISION: Balance = 10_000_000; pub type CERE = Balance; pub type USD = Balance; @@ -15,10 +17,10 @@ pub struct CurrencyConverter { } impl CurrencyConverter { - - pub fn new(rate: Balance) -> Self { + + pub fn new() -> Self { Self { - rate + rate: PRECISION } } diff --git a/bucket/ddc_bucket/network_fee.rs b/bucket/ddc_bucket/network_fee.rs deleted file mode 100644 index 25b277f1..00000000 --- a/bucket/ddc_bucket/network_fee.rs +++ /dev/null @@ -1,59 +0,0 @@ -//! This module captures fees on behalf of the entire Cere network. - -use ink_storage::traits::{SpreadAllocate, SpreadLayout}; -use scale::{Decode, Encode}; - -use crate::ddc_bucket::{AccountId, Balance, DdcBucket, Result}; -use crate::ddc_bucket::cash::Cash; -use crate::ddc_bucket::perm::entity::Permission; - -pub type BasisPoints = Balance; - -const BP: BasisPoints = 10_000; // 100% - -#[derive(SpreadAllocate, SpreadLayout, Default)] -#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] -pub struct NetworkFeeStore { - pub fee_config: FeeConfig, -} - -impl NetworkFeeStore { - pub fn cluster_management_fee_bp(&self) -> BasisPoints { - self.fee_config.cluster_management_fee_bp - } -} - -/// The configuration of fees. -#[derive(SpreadAllocate, SpreadLayout, Default, Decode, Encode)] -#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug, scale_info::TypeInfo))] -pub struct FeeConfig { - /// The fee rate from cluster revenues to the overall network. In basis points (1% of 1%). - pub network_fee_bp: BasisPoints, - /// The destination account of network fees. Use the 0 account to burn the fees. - pub network_fee_destination: AccountId, - /// The fee rate from cluster revenues to the cluster manager. In basis points (1% of 1%). - pub cluster_management_fee_bp: BasisPoints, -} - - -impl DdcBucket { - /// Take a network fee from the given revenues (in place). - pub fn capture_network_fee(store: &NetworkFeeStore, revenues: &mut Cash) -> Result<()> { - let config = &store.fee_config; - Self::capture_fee(config.network_fee_bp, config.network_fee_destination, revenues) - } - - /// Take a fee from the given revenues (in place) and send it to the destination. - pub fn capture_fee(rate_bp: Balance, destination: AccountId, revenues: &mut Cash) -> Result<()> { - let fee = revenues.peek() * rate_bp / BP; - let (payable, cash) = Cash::borrow_payable_cash(fee); - revenues.pay(payable)?; - Self::send_cash(destination, cash) - } - - pub fn message_admin_set_fee_config(&mut self, config: FeeConfig) -> Result<()> { - self.only_with_permission(Permission::SuperAdmin)?; - self.network_fee.fee_config = config; - Ok(()) - } -} diff --git a/bucket/ddc_bucket/protocol/messages.rs b/bucket/ddc_bucket/protocol/messages.rs index 042f3376..952c03fa 100644 --- a/bucket/ddc_bucket/protocol/messages.rs +++ b/bucket/ddc_bucket/protocol/messages.rs @@ -2,18 +2,18 @@ use crate::ddc_bucket::{DdcBucket, Result}; use crate::ddc_bucket::cash::{Cash, Payable}; +use crate::ddc_bucket::perm::entity::Permission; impl DdcBucket { - pub fn message_get_fee_bp(&self) -> u32 { - self.protocol.get_fee_bp() + pub fn message_get_protocol_fee_bp(&self) -> u128 { + self.protocol.get_protocol_fee_bp() } - pub fn message_set_fee_bp(&mut self, fee_bp: u32) -> Result<()> { - match self.protocol.set_fee_bp(fee_bp) { - Err(_e) => panic!("Setting fee failed"), - Ok(_v) => Ok(()), - } + pub fn message_set_protocol_fee_bp(&mut self, protocol_fee_bp: u128) -> Result<()> { + self.only_with_permission(Permission::SuperAdmin)?; + self.protocol.set_protocol_fee_bp(protocol_fee_bp); + Ok(()) } pub fn message_get_fee_revenues(&self) -> Cash { @@ -22,16 +22,14 @@ impl DdcBucket { pub fn message_put_fee_revenues(&mut self, amount: Cash) -> Result<()> { self.protocol.put_revenues(amount); - Ok(()) } pub fn message_withdraw_revenues(&mut self, amount: u128) -> Result<()> { + self.only_with_permission(Permission::SuperAdmin)?; self.protocol.withdraw_revenues(Payable(amount))?; - - Self::send_cash(self.protocol.admin, Cash(amount))?; - + Self::send_cash(self.protocol.protocol_fee_destination, Cash(amount))?; Ok(()) } - + } \ No newline at end of file diff --git a/bucket/ddc_bucket/protocol/store.rs b/bucket/ddc_bucket/protocol/store.rs index dd2f598d..1df93501 100644 --- a/bucket/ddc_bucket/protocol/store.rs +++ b/bucket/ddc_bucket/protocol/store.rs @@ -2,49 +2,95 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout}; use scale::{Decode, Encode}; -use crate::ddc_bucket::{AccountId, Error::*, Result, PRECISION}; +use crate::ddc_bucket::{DdcBucket, AccountId, Error::*, Result, Balance, BASIS_POINTS}; use crate::ddc_bucket::cash::{Cash, Payable}; use crate::ddc_bucket::currency::CurrencyConverter; +use crate::ddc_bucket::perm::entity::Permission; + + +pub type BasisPoints = u128; + +/// The configuration of fees. +#[derive(Default, Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] +#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug, scale_info::TypeInfo))] +pub struct NetworkFeeConfig { + /// The fee rate from cluster revenues to the overall network. In basis points (1% of 1%). + pub network_fee_bp: BasisPoints, + /// The destination account of network fees. Use the 0 account to burn the fees. + pub network_fee_destination: AccountId, + /// The fee rate from cluster revenues to the cluster manager. In basis points (1% of 1%). + pub cluster_management_fee_bp: BasisPoints, +} #[derive(Default, Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug, scale_info::TypeInfo))] pub struct ProtocolStore { - pub admin: AccountId, - pub fee_bp: u32, - pub revenues: Cash, - pub curr_converter: CurrencyConverter, + pub protocol_fee_bp: u128, + pub protocol_fee_destination: AccountId, + pub revenues: Cash, + pub curr_converter: CurrencyConverter, + pub network_fee_config: NetworkFeeConfig, } impl ProtocolStore { - pub fn init(&mut self, admin: AccountId, fee_bp: u32) { - self.admin = admin; - self.fee_bp = fee_bp; - self.curr_converter = CurrencyConverter::new(PRECISION); - } - - pub fn get_fee_bp(&self) -> u32 { - self.fee_bp - } - - pub fn set_fee_bp(&mut self, fee_bp: u32) -> Result<()> { - self.fee_bp = fee_bp; - Ok(()) - } - - pub fn get_fee_revenues(&self) -> Cash { - self.revenues - } - - pub fn put_revenues(&mut self, amount: Cash) { - self.revenues.increase(amount); - } - - pub fn withdraw_revenues(&mut self, amount: Payable) -> Result<()> { - if amount.peek() > self.revenues.peek() { - return Err(InsufficientBalance); - } - self.revenues.pay_unchecked(amount); - Ok(()) - } + pub fn init(&mut self, protocol_fee_destination: AccountId, protocol_fee_bp: u128) { + self.protocol_fee_bp = protocol_fee_bp; + self.protocol_fee_destination = protocol_fee_destination; + self.curr_converter = CurrencyConverter::new(); + } + + pub fn get_protocol_fee_bp(&self) -> u128 { + self.protocol_fee_bp + } + + pub fn set_protocol_fee_bp(&mut self, protocol_fee_bp: u128) { + self.protocol_fee_bp = protocol_fee_bp; + } + + pub fn get_fee_revenues(&self) -> Cash { + self.revenues + } + + pub fn put_revenues(&mut self, amount: Cash) { + self.revenues.increase(amount); + } + + pub fn withdraw_revenues(&mut self, amount: Payable) -> Result<()> { + if amount.peek() > self.revenues.peek() { + return Err(InsufficientBalance); + } + self.revenues.pay_unchecked(amount); + Ok(()) + } + + pub fn cluster_management_fee_bp(&self) -> BasisPoints { + self.network_fee_config.cluster_management_fee_bp + } + +} + +impl DdcBucket { + /// Take a network fee from the given revenues (in place). + pub fn capture_network_fee(&mut self, revenues: &mut Cash) -> Result<()> { + self.capture_fee( + self.protocol.network_fee_config.network_fee_bp, + self.protocol.network_fee_config.network_fee_destination, + revenues + ) + } + + /// Take a fee from the given revenues (in place) and send it to the destination. + pub fn capture_fee(&self, rate_bp: Balance, destination: AccountId, revenues: &mut Cash) -> Result<()> { + let fee = revenues.peek() * rate_bp / BASIS_POINTS; + let (payable, cash) = Cash::borrow_payable_cash(fee); + revenues.pay(payable)?; + Self::send_cash(destination, cash) + } + + pub fn message_admin_set_network_fee_config(&mut self, config: NetworkFeeConfig) -> Result<()> { + self.only_with_permission(Permission::SuperAdmin)?; + self.protocol.network_fee_config = config; + Ok(()) + } } \ No newline at end of file diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index b8a9d333..b577a247 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -1077,14 +1077,14 @@ fn cluster_distribute_revenue_ok() { let network_fee_bp = 100; // 1% let cluster_management_fee_bp = 200; // 2% set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); - ctx.contract.admin_set_fee_config(FeeConfig { + ctx.contract.admin_set_network_fee_config(NetworkFeeConfig { network_fee_bp, network_fee_destination: AccountId::default(), cluster_management_fee_bp, }); - let burned_fee = to_distribute * network_fee_bp / 10_000; - let manager_fee = (to_distribute - burned_fee) * cluster_management_fee_bp / 10_000; + let burned_fee = to_distribute * network_fee_bp / BASIS_POINTS; + let manager_fee = (to_distribute - burned_fee) * cluster_management_fee_bp / BASIS_POINTS; let provider_fee: u128 = (to_distribute - burned_fee - manager_fee) / 3; // Distribute the revenues of the cluster to providers. @@ -1527,9 +1527,10 @@ fn cluster_distribute_cdn_revenue_ok() { set_caller_value(ctx.provider_id0, 10 * TOKEN); ctx.contract.account_bond(5 * TOKEN); - set_caller(ctx.provider_id0); - ctx.contract.set_fee_bp(1_000); + set_caller(admin_id()); + ctx.contract.admin_set_protocol_fee_bp(1_000); + set_caller(ctx.provider_id0); let account0_before_putting = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); println!("Before putting revenue: {:?}", account0_before_putting); @@ -1559,7 +1560,7 @@ fn cluster_distribute_cdn_revenue_ok() { let validated_commit_node0 = ctx.contract.get_validated_commit(ctx.cdn_node_key0); println!("Validated commit: {:?}", validated_commit_node0); - let fee = ctx.contract.get_fee_bp(); + let fee = ctx.contract.get_protocol_fee_bp(); println!("Protocol fee in basis points: {:?}", fee); let protocol_revenues = ctx.contract.get_protocol_revenues(); diff --git a/bucket/lib.rs b/bucket/lib.rs index 61886f1b..5b1418b9 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -22,12 +22,11 @@ pub mod ddc_bucket { use topology::store::*; use crate::ddc_bucket::cdn_node::store::CdnNodeStore; - use crate::ddc_bucket::network_fee::{NetworkFeeStore, FeeConfig}; use crate::ddc_bucket::perm::entity::Permission; use self::cdn_node::entity::{CdnNodeInfo, CdnNodeKey, CdnNodeParams}; use self::account::entity::Account; - use self::protocol::store::ProtocolStore; + use self::protocol::store::{ProtocolStore, NetworkFeeConfig}; use self::topology::store::TopologyStore; pub mod account; @@ -39,7 +38,6 @@ pub mod ddc_bucket { pub mod committer; pub mod currency; pub mod flow; - pub mod network_fee; pub mod node; pub mod perm; pub mod protocol; @@ -58,7 +56,6 @@ pub mod ddc_bucket { nodes: NodeStore, topology: TopologyStore, accounts: AccountStore, - network_fee: NetworkFeeStore, committer: CommitterStore, protocol: ProtocolStore, } @@ -74,7 +71,7 @@ pub mod ddc_bucket { // Make the creator of this contract a super-admin. contract.perms.grant_permission(admin, Permission::SuperAdmin); contract.committer.init(admin); - contract.protocol.init(admin, DEFAULT_BASIS_POINTS); + contract.protocol.init(admin, DEFAULT_PROTOCOL_FEE_BP); }) } } @@ -1272,14 +1269,8 @@ pub mod ddc_bucket { impl DdcBucket { /// Get the Fee Percentage Basis Points that will be charged by the protocol #[ink(message)] - pub fn get_fee_bp(&self) -> u32 { - self.message_get_fee_bp() - } - - /// Return the last commit submitted by CDN node operator - #[ink(message)] - pub fn set_fee_bp(&mut self, fee_bp: u32) -> () { - self.message_set_fee_bp(fee_bp).unwrap(); + pub fn get_protocol_fee_bp(&self) -> u128 { + self.message_get_protocol_fee_bp() } /// Return fees accumulated by the protocol @@ -1287,12 +1278,6 @@ pub mod ddc_bucket { pub fn get_protocol_revenues(&self) -> Cash { self.message_get_fee_revenues() } - - /// Pay the revenues accumulated by the protocol - #[ink(message)] - pub fn protocol_withdraw_revenues(&mut self, amount: u128) -> () { - self.message_withdraw_revenues(amount).unwrap(); - } } // ---- End Protocol ---- @@ -1617,9 +1602,21 @@ pub mod ddc_bucket { /// As SuperAdmin, set the network and cluster fee configuration. #[ink(message)] - pub fn admin_set_fee_config(&mut self, config: FeeConfig) { - self.message_admin_set_fee_config(config).unwrap(); + pub fn admin_set_network_fee_config(&mut self, config: NetworkFeeConfig) { + self.message_admin_set_network_fee_config(config).unwrap(); + } + + /// Pay the revenues accumulated by the protocol + #[ink(message)] + pub fn admin_withdraw_protocol_revenues(&mut self, amount: u128) -> () { + self.message_withdraw_revenues(amount).unwrap(); + } + + #[ink(message)] + pub fn admin_set_protocol_fee_bp(&mut self, protocol_fee_bp: u128) -> () { + self.message_set_protocol_fee_bp(protocol_fee_bp).unwrap(); } + } // ---- End Admin ---- @@ -1654,11 +1651,13 @@ pub mod ddc_bucket { } // ---- End Topology ---- - // ---- Utils ---- + + // ---- Constants ---- /// One token with 10 decimals. pub const TOKEN: Balance = 10_000_000_000; - pub const DEFAULT_BASIS_POINTS: u32 = 500; - pub const PRECISION: Balance = 10_000_000; + pub const BASIS_POINTS: u128 = 10_000; // 100% + pub const DEFAULT_PROTOCOL_FEE_BP: u128 = 500; // 5 % + #[derive(Debug, PartialEq, Eq, Encode, Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] From 392f07f637f8e23ec2d48430922cb4924aae21b4 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Fri, 30 Jun 2023 02:10:44 +0200 Subject: [PATCH 71/89] chore(cluster): limits for vnodes in cluster --- bucket/ddc_bucket/admin.rs | 2 +- bucket/ddc_bucket/cluster/messages.rs | 7 +- bucket/ddc_bucket/tests/test_admin.rs | 2 +- bucket/ddc_bucket/tests/test_cluster.rs | 112 ++++++++++++++++++++++++ bucket/ddc_bucket/topology/store.rs | 38 +++++++- bucket/lib.rs | 16 ++-- 6 files changed, 166 insertions(+), 11 deletions(-) diff --git a/bucket/ddc_bucket/admin.rs b/bucket/ddc_bucket/admin.rs index f1041c38..7514b4fb 100644 --- a/bucket/ddc_bucket/admin.rs +++ b/bucket/ddc_bucket/admin.rs @@ -58,7 +58,7 @@ impl DdcBucket { let mut node = self.nodes.get(node_key)?; // allow node ownership transfer only if the current owner is the admin - node.only_provider(admin).map_err(|_| NodeOwnerIsNotSuperAdmin)?; + node.only_provider(admin).map_err(|_| NodeProviderIsNotSuperAdmin)?; node.provider_id = new_owner; self.nodes.update(node_key, &node)?; diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 5b0f6ef3..b04b5105 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -148,8 +148,11 @@ impl DdcBucket { self.nodes.update(new_node_key, &new_node)?; } - self.topology - .replace_node(cluster_id, new_node_key, v_nodes)?; + self.topology.replace_node( + cluster_id, + new_node_key, + v_nodes + )?; Self::env().emit_event(ClusterNodeReplaced { cluster_id, diff --git a/bucket/ddc_bucket/tests/test_admin.rs b/bucket/ddc_bucket/tests/test_admin.rs index 21581822..e7f36cf3 100644 --- a/bucket/ddc_bucket/tests/test_admin.rs +++ b/bucket/ddc_bucket/tests/test_admin.rs @@ -190,7 +190,7 @@ fn admin_transfer_node_ownership_err_if_provider_is_not_admin() { new_node_key, new_owner_id ), - Err(NodeOwnerIsNotSuperAdmin) + Err(NodeProviderIsNotSuperAdmin) ); } diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index b577a247..c3fe1ebb 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -341,6 +341,56 @@ fn cluster_add_node_err_if_not_cluster_manager() { } +#[ink::test] +fn cluster_add_node_err_if_no_v_nodes() { + let mut ctx = setup_cluster(); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + set_caller_value(ctx.provider_id0, 10); + ctx.contract.node_create( + new_node_key, + NodeParams::from("new_node"), + 1000000000, + 1 + )?; + + set_caller_value(ctx.manager_id, 10); + assert_eq!( + ctx.contract.cluster_add_node( + ctx.cluster_id, + new_node_key, + vec![], + ), + Err(AtLeastOneVNodeHasToBeAssigned(ctx.cluster_id, new_node_key)) + ); +} + + +#[ink::test] +fn cluster_add_node_err_if_v_nodes_exceeds_limit() { + let mut ctx = setup_cluster(); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + set_caller_value(ctx.provider_id0, 10); + ctx.contract.node_create( + new_node_key, + NodeParams::from("new_node"), + 1000000000, + 1 + )?; + + set_caller_value(ctx.manager_id, 10); + assert_eq!( + ctx.contract.cluster_add_node( + ctx.cluster_id, + new_node_key, + vec![100; 1801], + ), + Err(VNodesSizeExceedsLimit) + ); +} + + #[ink::test] fn cluster_add_node_ok() { let mut ctx = setup_cluster(); @@ -951,6 +1001,68 @@ fn cluster_replace_node_err_if_node_does_not_exist() { } +#[ink::test] +fn cluster_replace_node_err_if_no_v_nodes() { + let mut ctx = setup_cluster(); + + assert_eq!( + ctx.contract.cluster_replace_node( + ctx.cluster_id, + vec![], + ctx.node_key2 + ), + Err(AtLeastOneVNodeHasToBeAssigned(ctx.cluster_id, ctx.node_key2)) + ); +} + + +#[ink::test] +fn cluster_replace_node_err_if_v_nodes_exceeds_limit() { + let mut ctx = setup_cluster(); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + set_caller_value(ctx.provider_id0, 10); + ctx.contract.node_create( + new_node_key, + NodeParams::from("new_node"), + 1000000000, + 1 + )?; + + set_caller_value(ctx.manager_id, 10); + ctx.contract.cluster_add_node( + ctx.cluster_id, + new_node_key, + vec![100], + )?; + + let v_nodes: Vec = vec![100; 1801]; + assert_eq!( + ctx.contract.cluster_replace_node( + ctx.cluster_id, + v_nodes, + new_node_key + ), + Err(VNodesSizeExceedsLimit) + ); +} + + +#[ink::test] +fn cluster_replace_node_err_if_old_node_stays_without_v_nodes() { + let mut ctx = setup_cluster(); + + assert_eq!( + ctx.contract.cluster_replace_node( + ctx.cluster_id, + vec![1, 2, 3], + ctx.node_key2 + ), + Err(AtLeastOneVNodeHasToBeAssigned(ctx.cluster_id, ctx.node_key0)) + ); +} + + #[ink::test] fn cluster_replace_node_ok() { let mut ctx = setup_cluster(); diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index b9d5ed92..8f23a715 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -10,6 +10,10 @@ use crate::ddc_bucket::{Error::*, Result}; pub type VNodeToken = u64; pub type ClusterVNode = (ClusterId, VNodeToken); +// https://use.ink/datastructures/storage-layout#packed-vs-non-packed-layout +// There is a buffer with only limited capacity (around 16KB in the default configuration) available. +pub const MAX_V_NODE_IN_VECTOR: usize = 1800; + #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct TopologyStore { @@ -32,7 +36,7 @@ impl TopologyStore { } pub fn get_node_by_v_node(&self, cluster_id: ClusterId, v_node: VNodeToken) -> Result { - self.nodes_map.get((cluster_id, v_node)).ok_or(VNodeInNotAssignedToNode(cluster_id, v_node)) + self.nodes_map.get((cluster_id, v_node)).ok_or(VNodeIsNotAssignedToNode(cluster_id, v_node)) } pub fn v_node_has_node(&self, cluster_id: ClusterId, v_node: VNodeToken) -> bool { @@ -59,8 +63,20 @@ impl TopologyStore { v_nodes: Vec, ) -> Result<()> { + if v_nodes.is_empty() { + return Err(AtLeastOneVNodeHasToBeAssigned(cluster_id, node_key)); + } + + if v_nodes.len() > MAX_V_NODE_IN_VECTOR { + return Err(VNodesSizeExceedsLimit); + } + let mut cluster_v_nodes = self.get_v_nodes_by_cluster(cluster_id); + if cluster_v_nodes.len() + v_nodes.len() > MAX_V_NODE_IN_VECTOR { + return Err(VNodesSizeExceedsLimit); + } + for v_node in &v_nodes { // vnode that is being added should not exist in the cluster topology @@ -97,7 +113,7 @@ impl TopologyStore { // vnode that is being removed should exist in the cluster topology if !self.v_node_has_node(cluster_id, *v_node) { - return Err(VNodeInNotAssignedToNode(cluster_id, *v_node)); + return Err(VNodeIsNotAssignedToNode(cluster_id, *v_node)); } // vnode that is being removed should be unusigned from the physical node @@ -126,6 +142,14 @@ impl TopologyStore { v_nodes_to_reasign: Vec, ) -> Result<()> { + if v_nodes_to_reasign.is_empty() { + return Err(AtLeastOneVNodeHasToBeAssigned(cluster_id, new_node_key)); + } + + if v_nodes_to_reasign.len() > MAX_V_NODE_IN_VECTOR { + return Err(VNodesSizeExceedsLimit); + } + let cluster_v_nodes = self.get_v_nodes_by_cluster(cluster_id); for v_node in &v_nodes_to_reasign { @@ -145,6 +169,11 @@ impl TopologyStore { if let Some(pos) = old_node_v_nodes.iter().position(|x| *x == *v_node) { old_node_v_nodes.remove(pos); }; + + if old_node_v_nodes.is_empty() { + return Err(AtLeastOneVNodeHasToBeAssigned(cluster_id, old_node_key)); + } + self.v_nodes_map.insert(old_node_key, &old_node_v_nodes); // vnode that is being reasigned should be assined to the new physical node @@ -153,6 +182,11 @@ impl TopologyStore { // vnodes that are being reasigned should be among other vnodes assigned to the new physical node let mut new_node_v_nodes = self.get_v_nodes_by_node(new_node_key); + + if new_node_v_nodes.len() + v_nodes_to_reasign.len() > MAX_V_NODE_IN_VECTOR { + return Err(VNodesSizeExceedsLimit); + } + new_node_v_nodes.extend(v_nodes_to_reasign); self.v_nodes_map.insert(new_node_key, &new_node_v_nodes); diff --git a/bucket/lib.rs b/bucket/lib.rs index 5b1418b9..3460ed98 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -443,6 +443,8 @@ pub mod ddc_bucket { /// * `OnlyTrustedClusterManager` error if the caller is not a trusted cluster manager. /// * `NodeDoesNotExist` error if the adding Storage node does not exist. /// * `NodeIsAddedToCluster(ClusterId)` error if the adding Storage node is already added to this or another cluster. + /// * `AtLeastOneVNodeHasToBeAssigned(ClusterId, NodeKey)` error if there is a Storage node without any virtual nodes in the cluster. + /// * `VNodesSizeExceedsLimit` error if virtual nodes length exceeds storage capacity. #[ink(message, payable)] pub fn cluster_add_node( &mut self, @@ -513,13 +515,15 @@ pub mod ddc_bucket { /// * `NodeDoesNotExist` error if the new Storage node does not exist. /// * `NodeIsNotAddedToCluster(ClusterId)` error if the new Storage node is not added to this cluster. /// * `NodeIsAddedToCluster(ClusterId)` error if the new Storage node is in another cluster. - /// * `VNodeInNotAssignedToNode(ClusterId, VNodeToken)` error if the there is some virtual node that is being reasigned, but this virtual node is not assigned to any physical node. + /// * `VNodeIsNotAssignedToNode(ClusterId, VNodeToken)` error if the there is some virtual node that is being reasigned, but this virtual node is not assigned to any physical node. /// * `VNodeIsAlreadyAssignedToNode(NodeKey)` - error if there is some virtual node that is already assigned to other physical node within the same cluster. + /// * `AtLeastOneVNodeHasToBeAssigned(ClusterId, NodeKey)` error if there is a Storage node without any virtual nodes in the cluster. + /// * `VNodesSizeExceedsLimit` error if virtual nodes length exceeds storage capacity. #[ink(message)] pub fn cluster_replace_node( &mut self, cluster_id: ClusterId, - v_nodes: Vec, + v_nodes: Vec, new_node_key: NodeKey, ) -> Result<()> { self.message_cluster_replace_node( @@ -1550,7 +1554,7 @@ pub mod ddc_bucket { /// /// * `OnlySuperAdmin` error if the caller is not the Super-admin. /// * `NodeDoesNotExist` error if the Storage node does not exist. - /// * `NodeOwnerIsNotSuperAdmin` error if the owner of the targeting node is not the Super-admin. + /// * `NodeProviderIsNotSuperAdmin` error if the owner of the targeting node is not the Super-admin. #[ink(message)] pub fn admin_transfer_node_ownership( &mut self, @@ -1682,14 +1686,16 @@ pub mod ddc_bucket { ClusterIsNotEmpty, TopologyIsNotCreated(ClusterId), TopologyAlreadyExists, + VNodesSizeExceedsLimit, NodeIsNotAddedToCluster(ClusterId), NodeIsAddedToCluster(ClusterId), CdnNodeIsNotAddedToCluster(ClusterId), CdnNodeIsAddedToCluster(ClusterId), VNodeDoesNotExistsInCluster(ClusterId), - VNodeInNotAssignedToNode(ClusterId, VNodeToken), + VNodeIsNotAssignedToNode(ClusterId, VNodeToken), VNodeIsAlreadyAssignedToNode(NodeKey), - NodeOwnerIsNotSuperAdmin, + AtLeastOneVNodeHasToBeAssigned(ClusterId, NodeKey), + NodeProviderIsNotSuperAdmin, CdnNodeOwnerIsNotSuperAdmin, BucketDoesNotExist, BondingPeriodNotFinished, From a0f110dc4f7aa3d0dc0a909f97714265c218df84 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Fri, 30 Jun 2023 02:47:27 +0200 Subject: [PATCH 72/89] fix(lib): guards for packed layouts (vectors) are added --- bucket/ddc_bucket/account/messages.rs | 4 +-- bucket/ddc_bucket/account/store.rs | 12 ++++++++- bucket/ddc_bucket/bucket/messages.rs | 2 +- bucket/ddc_bucket/cdn_node/store.rs | 33 ++++++++++++++---------- bucket/ddc_bucket/cluster/entity.rs | 18 +++++++++++-- bucket/ddc_bucket/cluster/messages.rs | 4 +-- bucket/ddc_bucket/node/store.rs | 37 +++++++++++++++------------ bucket/ddc_bucket/topology/store.rs | 10 ++++---- bucket/lib.rs | 3 +++ 9 files changed, 81 insertions(+), 42 deletions(-) diff --git a/bucket/ddc_bucket/account/messages.rs b/bucket/ddc_bucket/account/messages.rs index c18ff5a5..81abb4ac 100644 --- a/bucket/ddc_bucket/account/messages.rs +++ b/bucket/ddc_bucket/account/messages.rs @@ -20,7 +20,7 @@ impl DdcBucket { let account_id = Self::env().caller(); // Create the account, if necessary. - self.accounts.create_if_not_exist(account_id); + self.accounts.create_if_not_exist(account_id)?; Self::env().emit_event(Deposit { account_id, value: cash.peek() }); @@ -126,7 +126,7 @@ impl DdcBucket { self._account_withdraw(from, payable)?; // Create the account, if necessary. - self.accounts.create_if_not_exist(to); + self.accounts.create_if_not_exist(to)?; let mut account = self.accounts.get(&to)?; account.deposit(cash); diff --git a/bucket/ddc_bucket/account/store.rs b/bucket/ddc_bucket/account/store.rs index 050bb134..edf98443 100644 --- a/bucket/ddc_bucket/account/store.rs +++ b/bucket/ddc_bucket/account/store.rs @@ -12,6 +12,11 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_prelude::vec::Vec; use super::entity::Account; + +// https://use.ink/datastructures/storage-layout#packed-vs-non-packed-layout +// There is a buffer with only limited capacity (around 16KB in the default configuration) available. +pub const MAX_ACCOUNTS_LEN_IN_VEC: usize = 400; + #[derive(Default, SpreadLayout, SpreadAllocate)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct AccountStore { @@ -23,12 +28,17 @@ pub struct AccountStore { impl AccountStore { /// Create a record for the given account if it does not exist yet. /// Does not return extra contract storage used, due to blockchain changes. - pub fn create_if_not_exist(&mut self, account_id: AccountId) { + pub fn create_if_not_exist(&mut self, account_id: AccountId) -> Result<()> { if !self.accounts.contains(account_id) { + if self.accounts_keys.len() + 1 > MAX_ACCOUNTS_LEN_IN_VEC { + return Err(AccountsSizeExceedsLimit); + } let acc = Account::new(); self.accounts.insert(account_id, &acc); self.accounts_keys.push(account_id); }; + + Ok(()) } pub fn balance(&self, account_id: &AccountId) -> Balance { diff --git a/bucket/ddc_bucket/bucket/messages.rs b/bucket/ddc_bucket/bucket/messages.rs index 1ddf397f..4ba98b4d 100644 --- a/bucket/ddc_bucket/bucket/messages.rs +++ b/bucket/ddc_bucket/bucket/messages.rs @@ -12,7 +12,7 @@ use super::entity::{Bucket, BucketId, BucketParams, BucketStatus}; impl DdcBucket { pub fn message_bucket_create(&mut self, bucket_params: BucketParams, cluster_id: ClusterId, owner_id: Option) -> Result { let owner_id = owner_id.unwrap_or(Self::env().caller()); - self.accounts.create_if_not_exist(owner_id); + self.accounts.create_if_not_exist(owner_id)?; let bucket_id = self.buckets.create(owner_id, cluster_id, bucket_params); Self::env().emit_event(BucketCreated { bucket_id, owner_id }); Ok(bucket_id) diff --git a/bucket/ddc_bucket/cdn_node/store.rs b/bucket/ddc_bucket/cdn_node/store.rs index 402df082..898c3011 100644 --- a/bucket/ddc_bucket/cdn_node/store.rs +++ b/bucket/ddc_bucket/cdn_node/store.rs @@ -3,16 +3,19 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_storage::Mapping; use ink_prelude::vec::Vec; - use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; use super::entity::{CdnNode, CdnNodeKey, CdnNodeParams}; +// https://use.ink/datastructures/storage-layout#packed-vs-non-packed-layout +// There is a buffer with only limited capacity (around 16KB in the default configuration) available. +pub const MAX_CDN_NODES_LEN_IN_VEC: usize = 400; + #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct CdnNodeStore { pub cdn_nodes: Mapping, - // This vector is temporal and must be replaced with an offchain indexer + // todo: remove this vector as it can store an arbitrary number of elements and easily exceed 16KB limit pub keys: Vec } @@ -26,18 +29,22 @@ impl CdnNodeStore { ) -> Result { if self.cdn_nodes.contains(&cdn_node_key) { - Err(CdnNodeAlreadyExists) - } else { - let cdn_node = CdnNode::new( - provider_id, - cdn_node_params, - undistributed_payment - )?; - self.cdn_nodes.insert(&cdn_node_key, &cdn_node); - self.keys.push(cdn_node_key); - Ok(cdn_node_key) + return Err(CdnNodeAlreadyExists); + } + + if self.keys.len() + 1 > MAX_CDN_NODES_LEN_IN_VEC { + return Err(CdnNodesSizeExceedsLimit); } - + + let cdn_node = CdnNode::new( + provider_id, + cdn_node_params, + undistributed_payment + )?; + self.cdn_nodes.insert(&cdn_node_key, &cdn_node); + self.keys.push(cdn_node_key); + Ok(cdn_node_key) + } pub fn get(&self, cdn_node_key: CdnNodeKey) -> Result { diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 1aa5c7e6..3151543c 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -14,6 +14,12 @@ use crate::ddc_bucket::{AccountId, Balance, VNodeToken, Result, Error::*}; pub type ClusterId = u32; pub type ClusterParams = String; +// https://use.ink/datastructures/storage-layout#packed-vs-non-packed-layout +// There is a buffer with only limited capacity (around 16KB in the default configuration) available. +pub const MAX_CLUSTER_NODES_LEN_IN_VEC: usize = 200; +pub const MAX_CLUSTER_CDN_NODES_LEN_IN_VEC: usize = 200; + + #[derive(Clone, PartialEq, Encode, Decode, SpreadAllocate, PackedLayout, SpreadLayout)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] pub struct Cluster { @@ -91,8 +97,12 @@ impl Cluster { } } - pub fn add_node(&mut self, node_key: NodeKey) { + pub fn add_node(&mut self, node_key: NodeKey) -> Result<()> { + if self.nodes_keys.len() + 1 > MAX_CLUSTER_NODES_LEN_IN_VEC { + return Err(NodesSizeExceedsLimit); + } self.nodes_keys.push(node_key); + Ok(()) } pub fn remove_node(&mut self, node_key: NodeKey) { @@ -101,8 +111,12 @@ impl Cluster { } } - pub fn add_cdn_node(&mut self, cdn_node_key: CdnNodeKey) { + pub fn add_cdn_node(&mut self, cdn_node_key: CdnNodeKey) -> Result<()> { + if self.cdn_nodes_keys.len() + 1 > MAX_CLUSTER_CDN_NODES_LEN_IN_VEC { + return Err(CdnNodesSizeExceedsLimit); + } self.cdn_nodes_keys.push(cdn_node_key); + Ok(()) } pub fn remove_cdn_node(&mut self, cdn_node_key: CdnNodeKey) { diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index b04b5105..fdfa60e4 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -65,7 +65,7 @@ impl DdcBucket { node.set_cluster(cluster_id, NodeStatusInCluster::ADDING); self.nodes.update(node_key, &node)?; - cluster.add_node(node_key); + cluster.add_node(node_key)?; for _v_node in &v_nodes { cluster.total_rent += node.rent_per_month; } @@ -180,7 +180,7 @@ impl DdcBucket { cdn_node.set_cluster(cluster_id, NodeStatusInCluster::ADDING); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; - cluster.add_cdn_node(cdn_node_key); + cluster.add_cdn_node(cdn_node_key)?; self.clusters.update(cluster_id, &cluster)?; Self::env().emit_event(ClusterCdnNodeAdded { diff --git a/bucket/ddc_bucket/node/store.rs b/bucket/ddc_bucket/node/store.rs index 69495574..e5f1f2cd 100644 --- a/bucket/ddc_bucket/node/store.rs +++ b/bucket/ddc_bucket/node/store.rs @@ -3,17 +3,18 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_prelude::vec::Vec; use ink_storage::Mapping; - -// use crate::ddc_bucket::node::entity::Resource; use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; - use super::entity::{Node, NodeKey, NodeParams, Resource}; +// https://use.ink/datastructures/storage-layout#packed-vs-non-packed-layout +// There is a buffer with only limited capacity (around 16KB in the default configuration) available. +pub const MAX_NODES_LEN_IN_VEC: usize = 400; + #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct NodeStore { pub nodes: Mapping, - // This pagination vector is temporal and must be replaced with an offchain indexer + // todo: remove this vector as it can store an arbitrary number of elements and easily exceed 16KB limit pub keys: Vec } @@ -28,19 +29,23 @@ impl NodeStore { ) -> Result { if self.nodes.contains(&node_key) { - Err(NodeAlreadyExists) - } else { - let node = Node::new( - provider_id, - node_params, - capacity, - rent_per_month - )?; - self.nodes.insert(node_key, &node); - self.keys.push(node_key); - Ok(node_key) + return Err(NodeAlreadyExists); + } + + if self.keys.len() + 1 > MAX_NODES_LEN_IN_VEC { + return Err(NodesSizeExceedsLimit); } - + + let node = Node::new( + provider_id, + node_params, + capacity, + rent_per_month + )?; + + self.nodes.insert(node_key, &node); + self.keys.push(node_key); + Ok(node_key) } pub fn get(&self, node_key: NodeKey) -> Result { diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index 8f23a715..88cf7f17 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -12,7 +12,7 @@ pub type ClusterVNode = (ClusterId, VNodeToken); // https://use.ink/datastructures/storage-layout#packed-vs-non-packed-layout // There is a buffer with only limited capacity (around 16KB in the default configuration) available. -pub const MAX_V_NODE_IN_VECTOR: usize = 1800; +pub const MAX_V_NODES_LEN_IN_VEC: usize = 1800; #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] @@ -67,13 +67,13 @@ impl TopologyStore { return Err(AtLeastOneVNodeHasToBeAssigned(cluster_id, node_key)); } - if v_nodes.len() > MAX_V_NODE_IN_VECTOR { + if v_nodes.len() > MAX_V_NODES_LEN_IN_VEC { return Err(VNodesSizeExceedsLimit); } let mut cluster_v_nodes = self.get_v_nodes_by_cluster(cluster_id); - if cluster_v_nodes.len() + v_nodes.len() > MAX_V_NODE_IN_VECTOR { + if cluster_v_nodes.len() + v_nodes.len() > MAX_V_NODES_LEN_IN_VEC { return Err(VNodesSizeExceedsLimit); } @@ -146,7 +146,7 @@ impl TopologyStore { return Err(AtLeastOneVNodeHasToBeAssigned(cluster_id, new_node_key)); } - if v_nodes_to_reasign.len() > MAX_V_NODE_IN_VECTOR { + if v_nodes_to_reasign.len() > MAX_V_NODES_LEN_IN_VEC { return Err(VNodesSizeExceedsLimit); } @@ -183,7 +183,7 @@ impl TopologyStore { // vnodes that are being reasigned should be among other vnodes assigned to the new physical node let mut new_node_v_nodes = self.get_v_nodes_by_node(new_node_key); - if new_node_v_nodes.len() + v_nodes_to_reasign.len() > MAX_V_NODE_IN_VECTOR { + if new_node_v_nodes.len() + v_nodes_to_reasign.len() > MAX_V_NODES_LEN_IN_VEC { return Err(VNodesSizeExceedsLimit); } diff --git a/bucket/lib.rs b/bucket/lib.rs index 3460ed98..a0545b4d 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -1686,7 +1686,10 @@ pub mod ddc_bucket { ClusterIsNotEmpty, TopologyIsNotCreated(ClusterId), TopologyAlreadyExists, + NodesSizeExceedsLimit, + CdnNodesSizeExceedsLimit, VNodesSizeExceedsLimit, + AccountsSizeExceedsLimit, NodeIsNotAddedToCluster(ClusterId), NodeIsAddedToCluster(ClusterId), CdnNodeIsNotAddedToCluster(ClusterId), From 6d05e320b5a3dc032762599c5c8a2a688190b37d Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Fri, 30 Jun 2023 12:46:27 +0200 Subject: [PATCH 73/89] chore(lib): returning the Result for mutable endpoints --- bucket/ddc_bucket/account/messages.rs | 7 +- bucket/ddc_bucket/bucket/messages.rs | 12 ++- bucket/ddc_bucket/bucket/store.rs | 6 +- bucket/ddc_bucket/committer/messages.rs | 11 ++- bucket/ddc_bucket/tests/setup_utils.rs | 8 +- bucket/ddc_bucket/tests/test_account.rs | 4 +- bucket/ddc_bucket/tests/test_admin.rs | 8 +- bucket/ddc_bucket/tests/test_bucket.rs | 14 +-- bucket/ddc_bucket/tests/test_cluster.rs | 22 ++--- bucket/ddc_bucket/tests/test_currency.rs | 10 +-- bucket/lib.rs | 105 ++++++++++------------- 11 files changed, 95 insertions(+), 112 deletions(-) diff --git a/bucket/ddc_bucket/account/messages.rs b/bucket/ddc_bucket/account/messages.rs index 81abb4ac..c5b1bcab 100644 --- a/bucket/ddc_bucket/account/messages.rs +++ b/bucket/ddc_bucket/account/messages.rs @@ -71,9 +71,10 @@ impl DdcBucket { self.protocol.curr_converter.to_usd(1 * TOKEN) } - pub fn message_account_set_usd_per_cere(&mut self, usd_per_cere: Balance) { - self.only_with_permission(Permission::SetExchangeRate).unwrap(); - self.protocol.curr_converter.set_usd_per_cere(usd_per_cere) + pub fn message_account_set_usd_per_cere(&mut self, usd_per_cere: Balance) -> Result<()> { + self.only_with_permission(Permission::SetExchangeRate)?; + self.protocol.curr_converter.set_usd_per_cere(usd_per_cere); + Ok(()) } pub fn receive_cash() -> Cash { diff --git a/bucket/ddc_bucket/bucket/messages.rs b/bucket/ddc_bucket/bucket/messages.rs index 4ba98b4d..148988a3 100644 --- a/bucket/ddc_bucket/bucket/messages.rs +++ b/bucket/ddc_bucket/bucket/messages.rs @@ -74,7 +74,7 @@ impl DdcBucket { } pub fn message_bucket_get(&self, bucket_id: BucketId) -> Result { - let bucket = self.buckets.get(bucket_id)?.clone(); + let bucket = self.buckets.get(bucket_id)?; self.bucket_calculate_status(bucket_id, bucket) } @@ -149,9 +149,8 @@ impl DdcBucket { Ok(()) } - pub fn message_get_bucket_writers(&mut self, bucket_id: BucketId) -> Result> { - let writers = self.buckets.get_bucket_writers(bucket_id); - Ok(writers) + pub fn message_get_bucket_writers(&mut self, bucket_id: BucketId) -> Vec { + self.buckets.get_bucket_writers(bucket_id) } pub fn message_grant_writer_permission(&mut self, bucket_id: BucketId, writer: AccountId) -> Result<()> { @@ -174,9 +173,8 @@ impl DdcBucket { Ok(()) } - pub fn message_get_bucket_readers(&mut self, bucket_id: BucketId) -> Result> { - let readers = self.buckets.get_bucket_readers(bucket_id); - Ok(readers) + pub fn message_get_bucket_readers(&mut self, bucket_id: BucketId) -> Vec { + self.buckets.get_bucket_readers(bucket_id) } pub fn message_grant_reader_permission(&mut self, bucket_id: BucketId, reader: AccountId) -> Result<()> { diff --git a/bucket/ddc_bucket/bucket/store.rs b/bucket/ddc_bucket/bucket/store.rs index 486b44bb..6c44f032 100644 --- a/bucket/ddc_bucket/bucket/store.rs +++ b/bucket/ddc_bucket/bucket/store.rs @@ -88,13 +88,11 @@ impl BucketStore { // get accounts with permission for bucket reading pub fn get_bucket_readers(&self, key: BucketId) -> Vec { - let readers = self.readers.get(&key) + self.readers.get(&key) .unwrap_or(Vec::new()) .iter() .cloned() - .collect(); - - return readers; + .collect() } // grant permission for bucket reading for some account diff --git a/bucket/ddc_bucket/committer/messages.rs b/bucket/ddc_bucket/committer/messages.rs index bfbd5e86..35782dc4 100644 --- a/bucket/ddc_bucket/committer/messages.rs +++ b/bucket/ddc_bucket/committer/messages.rs @@ -1,16 +1,15 @@ use ink_lang::codegen::StaticEnv; -use ink_env::Error; use ink_prelude::vec::Vec; -use crate::ddc_bucket::{AccountId, DdcBucket, CdnNodeKey}; +use crate::ddc_bucket::{AccountId, DdcBucket, CdnNodeKey, Result, Error::*}; use super::store::{Commit, EraConfig, EraStatus, EraAndTimestamp}; -pub type Result = core::result::Result; impl DdcBucket { - pub fn message_set_commit(&mut self, cdn_owner: AccountId, cdn_node_key: CdnNodeKey, commit: Commit) { + pub fn message_set_commit(&mut self, cdn_owner: AccountId, cdn_node_key: CdnNodeKey, commit: Commit) -> Result<()> { self.committer.set_commit(cdn_owner, cdn_node_key, commit); + Ok(()) } pub fn message_get_commit(&self, cdn_owner: AccountId) -> Vec<(CdnNodeKey, Commit)> { @@ -25,7 +24,7 @@ impl DdcBucket { let caller = Self::env().caller(); match self.committer.set_era(caller, era_config) { - Err(_e) => panic!("Setting era failed"), + Err(_e) => Err(EraSettingFailed), Ok(_v) => Ok(()), } } @@ -38,5 +37,5 @@ impl DdcBucket { pub fn message_get_era_settings(&self) -> EraConfig { self.committer.get_era_settings() } - + } \ No newline at end of file diff --git a/bucket/ddc_bucket/tests/setup_utils.rs b/bucket/ddc_bucket/tests/setup_utils.rs index 67350277..132ff3d5 100644 --- a/bucket/ddc_bucket/tests/setup_utils.rs +++ b/bucket/ddc_bucket/tests/setup_utils.rs @@ -210,7 +210,7 @@ pub fn setup_cluster() -> TestCluster { set_caller(manager_id); - contract.cluster_reserve_resource(cluster_id, reserved_resource); + contract.cluster_reserve_resource(cluster_id, reserved_resource).unwrap(); let nodes_keys = vec![ @@ -281,16 +281,16 @@ pub fn setup_bucket(ctx: &mut TestCluster) -> TestBucket { "{}".to_string(), ctx.cluster_id, None - ); + ).unwrap(); // Reserve some resources for the bucket from the cluster. set_caller_value(owner_id, CONTRACT_FEE_LIMIT); let resource = 1; - ctx.contract.bucket_alloc_into_cluster(bucket_id, resource); + ctx.contract.bucket_alloc_into_cluster(bucket_id, resource).unwrap(); // Deposit some value to pay for buckets. set_caller_value(owner_id, 10 * TOKEN); - ctx.contract.account_deposit(); + ctx.contract.account_deposit().unwrap(); TestBucket { bucket_id, diff --git a/bucket/ddc_bucket/tests/test_account.rs b/bucket/ddc_bucket/tests/test_account.rs index 8a7c8cac..51a70fd7 100644 --- a/bucket/ddc_bucket/tests/test_account.rs +++ b/bucket/ddc_bucket/tests/test_account.rs @@ -25,7 +25,7 @@ fn account_deposit_ok() { // Deposit some value. set_caller_value(account_id, deposit); - contract.account_deposit(); + contract.account_deposit()?; let account = contract.account_get(account_id)?; assert_eq!( @@ -43,7 +43,7 @@ fn account_deposit_ok() { // Deposit more value. set_caller_value(account_id, deposit); - contract.account_deposit(); + contract.account_deposit()?; let account = contract.account_get(account_id)?; assert_eq!( diff --git a/bucket/ddc_bucket/tests/test_admin.rs b/bucket/ddc_bucket/tests/test_admin.rs index e7f36cf3..6b54be8f 100644 --- a/bucket/ddc_bucket/tests/test_admin.rs +++ b/bucket/ddc_bucket/tests/test_admin.rs @@ -31,7 +31,7 @@ fn admin_withdraw_ok() { set_caller(admin_id()); - contract.admin_withdraw(9); + contract.admin_withdraw(9).unwrap(); assert_eq!(balance_of(contract_id()), 1); } @@ -43,7 +43,7 @@ fn admin_withdraw_err_if_not_admin() { set_caller(not_admin_id()); - contract.admin_withdraw(9); // panic. + contract.admin_withdraw(9).unwrap(); // panic. } @@ -67,7 +67,7 @@ fn admin_grant_ok() { set_caller(new_admin_id); - contract.admin_withdraw(9); + contract.admin_withdraw(9).unwrap(); } @@ -107,7 +107,7 @@ fn admin_revoke_ok() { // Cannot withdraw because no more permission. set_caller(admin_id()); - contract.admin_withdraw(9); // panic. + contract.admin_withdraw(9)?; } diff --git a/bucket/ddc_bucket/tests/test_bucket.rs b/bucket/ddc_bucket/tests/test_bucket.rs index a5e5996e..4214c261 100644 --- a/bucket/ddc_bucket/tests/test_bucket.rs +++ b/bucket/ddc_bucket/tests/test_bucket.rs @@ -34,7 +34,7 @@ fn do_bucket_pays_cluster( advance_block::(); // Pay the due thus far. set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); - ctx.contract.bucket_settle_payment(test_bucket.bucket_id); + ctx.contract.bucket_settle_payment(test_bucket.bucket_id)?; let timestamp_after = block_timestamp::(); // Check the last event. @@ -103,7 +103,7 @@ fn bucket_pays_cluster_at_new_rate_ok() { // Change the currency exchange rate. let usd_per_cere = 2; set_caller(admin_id()); - ctx.contract.account_set_usd_per_cere(usd_per_cere * TOKEN); + ctx.contract.account_set_usd_per_cere(usd_per_cere * TOKEN)?; do_bucket_pays_cluster(ctx, test_bucket, usd_per_cere).unwrap(); } @@ -176,7 +176,7 @@ fn bucket_change_params_ok() { // Change params. set_caller_value(test_bucket.owner_id, CONTRACT_FEE_LIMIT); ctx.contract - .bucket_change_params(test_bucket.bucket_id, "new params".to_string()); + .bucket_change_params(test_bucket.bucket_id, "new params".to_string())?; // Check the changed params. let status = ctx.contract.bucket_get(test_bucket.bucket_id)?; @@ -192,7 +192,7 @@ fn bucket_change_params_only_owner() { // Change params. set_caller_value(get_accounts().bob, CONTRACT_FEE_LIMIT); ctx.contract - .bucket_change_params(test_bucket.bucket_id, "new params".to_string()); + .bucket_change_params(test_bucket.bucket_id, "new params".to_string())?; // Panic. } @@ -211,11 +211,11 @@ fn bucket_list_ok() { let cluster_id = 0; set_caller_value(owner_id1, CONTRACT_FEE_LIMIT); - let bucket_id1 = ddc_bucket.bucket_create("".to_string(), cluster_id, None); - let bucket_status1 = ddc_bucket.bucket_get(bucket_id1).unwrap(); + let bucket_id1 = ddc_bucket.bucket_create("".to_string(), cluster_id, None)?; + let bucket_status1 = ddc_bucket.bucket_get(bucket_id1)?; set_caller_value(owner_id2, CONTRACT_FEE_LIMIT); - let bucket_id2 = ddc_bucket.bucket_create("".to_string(), cluster_id, None); + let bucket_id2 = ddc_bucket.bucket_create("".to_string(), cluster_id, None)?; let bucket_status2 = ddc_bucket.bucket_get(bucket_id2)?; assert_ne!(bucket_id1, bucket_id2); diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index c3fe1ebb..570742ba 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -1129,7 +1129,7 @@ fn cluster_reserve_resource_ok() { set_caller(ctx.manager_id); // Reserve more resources. - ctx.contract.cluster_reserve_resource(ctx.cluster_id, 5); + ctx.contract.cluster_reserve_resource(ctx.cluster_id, 5)?; // Check the last event. let ev = get_events().pop().unwrap(); @@ -1168,7 +1168,7 @@ fn cluster_distribute_revenue_ok() { advance_block::(); // Pay the due thus far. set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); - ctx.contract.bucket_settle_payment(test_bucket.bucket_id); + ctx.contract.bucket_settle_payment(test_bucket.bucket_id)?; // Get state before the distribution. let to_distribute = ctx @@ -1193,14 +1193,14 @@ fn cluster_distribute_revenue_ok() { network_fee_bp, network_fee_destination: AccountId::default(), cluster_management_fee_bp, - }); + })?; let burned_fee = to_distribute * network_fee_bp / BASIS_POINTS; let manager_fee = (to_distribute - burned_fee) * cluster_management_fee_bp / BASIS_POINTS; let provider_fee: u128 = (to_distribute - burned_fee - manager_fee) / 3; // Distribute the revenues of the cluster to providers. - ctx.contract.cluster_distribute_revenues(ctx.cluster_id); + ctx.contract.cluster_distribute_revenues(ctx.cluster_id)?; // Check the last events. let mut events = get_events(); @@ -1619,12 +1619,12 @@ fn cluster_distribute_cdn_revenue_ok() { let usd_per_cere = TOKEN / 100; set_caller(admin_id()); - ctx.contract.account_set_usd_per_cere(usd_per_cere); + ctx.contract.account_set_usd_per_cere(usd_per_cere)?; let usd_amount = ctx.contract.account_get_usd_per_cere(); println!("Current usd amount is {}", usd_amount); - let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); + let rate = ctx.contract.cdn_get_rate(ctx.cluster_id)?; println!("The current rate is {}", rate); let usd_per_kb = rate / KB_PER_GB; @@ -1634,13 +1634,13 @@ fn cluster_distribute_cdn_revenue_ok() { println!("The current cere rate per kb {}", cere_per_kb); set_caller_value(ctx.provider_id0, 10 * TOKEN); - ctx.contract.account_deposit(); + ctx.contract.account_deposit()?; set_caller_value(ctx.provider_id0, 10 * TOKEN); - ctx.contract.account_bond(5 * TOKEN); + ctx.contract.account_bond(5 * TOKEN)?; set_caller(admin_id()); - ctx.contract.admin_set_protocol_fee_bp(1_000); + ctx.contract.admin_set_protocol_fee_bp(1_000)?; set_caller(ctx.provider_id0); let account0_before_putting = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); @@ -1652,7 +1652,7 @@ fn cluster_distribute_cdn_revenue_ok() { vec![(ctx.cdn_node_key0, 1000), (ctx.cdn_node_key1, 541643)], vec![], 5, - ); + )?; let account0_after_putting = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); println!("After putting revenue: {:?}", account0_after_putting); @@ -1680,7 +1680,7 @@ fn cluster_distribute_cdn_revenue_ok() { set_caller(ctx.provider_id0); - ctx.contract.cluster_distribute_cdn_revenue(ctx.cluster_id); + ctx.contract.cluster_distribute_cdn_revenue(ctx.cluster_id)?; let cdn_node0 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key0).unwrap(); let cdn_node1 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key1).unwrap(); diff --git a/bucket/ddc_bucket/tests/test_currency.rs b/bucket/ddc_bucket/tests/test_currency.rs index 3050f6f0..2d1e86be 100644 --- a/bucket/ddc_bucket/tests/test_currency.rs +++ b/bucket/ddc_bucket/tests/test_currency.rs @@ -25,7 +25,7 @@ fn currency_conversion_set_rate_ok() { println!("{}", usd_per_cere); set_caller(admin_id()); - contract.account_set_usd_per_cere(usd_per_cere); + contract.account_set_usd_per_cere(usd_per_cere)?; assert_eq!( contract.account_get_usd_per_cere(), @@ -42,7 +42,7 @@ fn currency_conversion_set_rate_err_if_not_admin() { let not_admin = get_accounts().bob; set_caller(not_admin); - contract.account_set_usd_per_cere(9); + contract.account_set_usd_per_cere(9)?; } @@ -56,13 +56,13 @@ fn converter_ok() { // The provider stops trusting the manager_id. println!("Cdn cluster id is {}", ctx.cluster_id); set_caller(ctx.manager_id); - ctx.contract.cdn_set_rate(ctx.cluster_id, 3_750_000_000); + ctx.contract.cdn_set_rate(ctx.cluster_id, 3_750_000_000)?; set_caller(ctx.provider_id0); - let rate = ctx.contract.cdn_get_rate(ctx.cluster_id); + let rate = ctx.contract.cdn_get_rate(ctx.cluster_id)?; let usd_per_cere = TOKEN / 100; set_caller(admin_id()); - ctx.contract.account_set_usd_per_cere(usd_per_cere); + ctx.contract.account_set_usd_per_cere(usd_per_cere)?; let usd_amount = ctx.contract.account_get_usd_per_cere(); println!("Current usd amount is {}", usd_amount); diff --git a/bucket/lib.rs b/bucket/lib.rs index a0545b4d..f3ce4149 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -142,42 +142,38 @@ pub mod ddc_bucket { bucket_params: BucketParams, cluster_id: ClusterId, owner_id: Option, - ) -> BucketId { + ) -> Result { self.message_bucket_create(bucket_params, cluster_id, owner_id) - .unwrap() } /// Change owner of the bucket /// /// Provide the account of new owner #[ink(message, payable)] - pub fn bucket_change_owner(&mut self, bucket_id: BucketId, owner_id: AccountId) -> () { + pub fn bucket_change_owner(&mut self, bucket_id: BucketId, owner_id: AccountId) -> Result<()> { self.message_bucket_change_owner(bucket_id, owner_id) - .unwrap() } /// Allocate some resources of a cluster to a bucket. /// /// The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes). #[ink(message)] - pub fn bucket_alloc_into_cluster(&mut self, bucket_id: BucketId, resource: Resource) -> () { + pub fn bucket_alloc_into_cluster(&mut self, bucket_id: BucketId, resource: Resource) -> Result<()> { self.message_bucket_alloc_into_cluster(bucket_id, resource) - .unwrap() } /// Settle the due costs of a bucket from its payer account to the cluster account. #[ink(message)] - pub fn bucket_settle_payment(&mut self, bucket_id: BucketId) { - self.message_bucket_settle_payment(bucket_id).unwrap() + pub fn bucket_settle_payment(&mut self, bucket_id: BucketId) -> Result<()> { + self.message_bucket_settle_payment(bucket_id) } /// Change the `bucket_params`, which is configuration used by clients and nodes. /// /// See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema) #[ink(message, payable)] - pub fn bucket_change_params(&mut self, bucket_id: BucketId, params: BucketParams) { + pub fn bucket_change_params(&mut self, bucket_id: BucketId, params: BucketParams) -> Result<()> { self.message_bucket_change_params(bucket_id, params) - .unwrap(); } /// Get the current status of a bucket. @@ -216,9 +212,8 @@ pub mod ddc_bucket { &mut self, bucket_id: BucketId, public_availability: bool, - ) -> () { + ) -> Result<()> { self.message_bucket_set_availability(bucket_id, public_availability) - .unwrap() } /// Set max resource cap to be charged by CDN for public bucket @@ -227,49 +222,44 @@ pub mod ddc_bucket { &mut self, bucket_id: BucketId, new_resource_cap: Resource, - ) -> () { + ) -> Result<()> { self.message_bucket_set_resource_cap(bucket_id, new_resource_cap) - .unwrap() } /// Set permission for the reader of the bucket #[ink(message)] pub fn get_bucket_writers(&mut self, bucket_id: BucketId) -> Vec { - self.message_get_bucket_writers(bucket_id).unwrap() + self.message_get_bucket_writers(bucket_id) } /// Set permission for the writer of the bucket #[ink(message)] - pub fn bucket_set_writer_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { + pub fn bucket_set_writer_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> Result<()> { self.message_grant_writer_permission(bucket_id, writer) - .unwrap() } /// Revoke permission for the writer of the bucket #[ink(message)] - pub fn bucket_revoke_writer_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { + pub fn bucket_revoke_writer_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> Result<()> { self.message_revoke_writer_permission(bucket_id, writer) - .unwrap() } /// Set permission for the reader of the bucket #[ink(message)] pub fn get_bucket_readers(&mut self, bucket_id: BucketId) -> Vec { - self.message_get_bucket_readers(bucket_id).unwrap() + self.message_get_bucket_readers(bucket_id) } /// Set permission for the reader of the bucket #[ink(message)] - pub fn bucket_set_reader_perm(&mut self, bucket_id: BucketId, reader: AccountId) -> () { + pub fn bucket_set_reader_perm(&mut self, bucket_id: BucketId, reader: AccountId) -> Result<()> { self.message_grant_reader_permission(bucket_id, reader) - .unwrap() } /// Revoke permission for the reader of the bucket #[ink(message)] - pub fn bucket_revoke_reader_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> () { + pub fn bucket_revoke_reader_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> Result<()> { self.message_revoke_reader_permission(bucket_id, writer) - .unwrap() } } // ---- End Bucket ---- @@ -786,28 +776,26 @@ pub mod ddc_bucket { /// /// The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes). #[ink(message)] - pub fn cluster_reserve_resource(&mut self, cluster_id: ClusterId, amount: Resource) -> () { + pub fn cluster_reserve_resource(&mut self, cluster_id: ClusterId, amount: Resource) -> Result<()> { self.message_cluster_reserve_resource(cluster_id, amount) - .unwrap() } /// Trigger the distribution of revenues from the cluster to the providers. #[ink(message)] - pub fn cluster_distribute_revenues(&mut self, cluster_id: ClusterId) { + pub fn cluster_distribute_revenues(&mut self, cluster_id: ClusterId) -> Result<()> { self.message_cluster_distribute_revenues(cluster_id) - .unwrap() } /// Set rate for streaming (price per gb) #[ink(message, payable)] - pub fn cdn_set_rate(&mut self, cluster_id: ClusterId, usd_per_gb: Balance) -> () { - self.message_cdn_set_rate(cluster_id, usd_per_gb).unwrap() + pub fn cdn_set_rate(&mut self, cluster_id: ClusterId, usd_per_gb: Balance) -> Result<()> { + self.message_cdn_set_rate(cluster_id, usd_per_gb) } /// Get rate for streaming (price per gb) #[ink(message, payable)] - pub fn cdn_get_rate(&self, cluster_id: ClusterId) -> Balance { - self.message_cdn_get_rate(cluster_id).unwrap() + pub fn cdn_get_rate(&self, cluster_id: ClusterId) -> Result { + self.message_cdn_get_rate(cluster_id) } /// As validator, charge payments from users and allocate undistributed payments to CDN nodes. @@ -821,7 +809,7 @@ pub mod ddc_bucket { aggregates_nodes: Vec<(CdnNodeKey, u128)>, aggregates_buckets: Vec<(BucketId, Resource)>, era: u64, - ) -> () { + ) -> Result<()> { self.message_cluster_put_cdn_revenue( cluster_id, aggregates_accounts, @@ -829,7 +817,6 @@ pub mod ddc_bucket { aggregates_buckets, era, ) - .unwrap() } /// Trigger the distribution of revenues from the cluster to the CDN node providers. @@ -838,9 +825,8 @@ pub mod ddc_bucket { /// /// Undistributed payments will be trasnferred, CDN cluster revenue will decrease. #[ink(message)] - pub fn cluster_distribute_cdn_revenue(&mut self, cluster_id: ClusterId) { + pub fn cluster_distribute_cdn_revenue(&mut self, cluster_id: ClusterId) -> Result<()> { self.message_cluster_distribute_cdn_revenue(cluster_id) - .unwrap() } } @@ -875,8 +861,8 @@ pub mod ddc_bucket { impl DdcBucket { /// CDN node operator sets the commit for current era. #[ink(message)] - pub fn set_commit(&mut self, cdn_owner: AccountId, cdn_node_key: CdnNodeKey, commit: Commit) { - self.message_set_commit(cdn_owner, cdn_node_key, commit); + pub fn set_commit(&mut self, cdn_owner: AccountId, cdn_node_key: CdnNodeKey, commit: Commit) -> Result<()> { + self.message_set_commit(cdn_owner, cdn_node_key, commit) } /// Return the last commit submitted by CDN node operator @@ -893,8 +879,8 @@ pub mod ddc_bucket { /// Set the new configs for era #[ink(message)] - pub fn set_era(&mut self, era_config: EraConfig) -> () { - self.message_set_era(era_config).unwrap(); + pub fn set_era(&mut self, era_config: EraConfig) -> Result<()> { + self.message_set_era(era_config) } /// Return current status of an era @@ -1300,34 +1286,34 @@ pub mod ddc_bucket { /// As user, deposit tokens on the account of the caller from the transaction value. This deposit /// can be used to pay for the services to buckets of the account. #[ink(message, payable)] - pub fn account_deposit(&mut self) -> () { - self.message_account_deposit().unwrap() + pub fn account_deposit(&mut self) -> Result<()> { + self.message_account_deposit() } /// As user, bond some amount of tokens from the withdrawable balance. These funds will be used to pay for CDN node service. #[ink(message, payable)] - pub fn account_bond(&mut self, bond_amount: Balance) -> () { - self.message_account_bond(bond_amount).unwrap() + pub fn account_bond(&mut self, bond_amount: Balance) -> Result<()> { + self.message_account_bond(bond_amount) } /// As user, unbond a specified amount of tokens. The tokens will be locked for some time, as defined by contract owner. #[ink(message, payable)] - pub fn account_unbond(&mut self, amount_to_unbond: Cash) -> () { - self.message_account_unbond(amount_to_unbond).unwrap() + pub fn account_unbond(&mut self, amount_to_unbond: Cash) -> Result<()> { + self.message_account_unbond(amount_to_unbond) } /// As user, move the unbonded tokens back to withdrawable balance state. /// /// This can be triggered after unbonded_timestamp #[ink(message, payable)] - pub fn account_withdraw_unbonded(&mut self) -> () { - self.message_account_withdraw_unbonded().unwrap() + pub fn account_withdraw_unbonded(&mut self) -> Result<()> { + self.message_account_withdraw_unbonded() } /// Get the current status of an account. #[ink(message)] pub fn account_get(&self, account_id: AccountId) -> Result { - Ok(self.accounts.get(&account_id)?.clone()) + self.accounts.get(&account_id) } /// Get the current conversion rate between the native currency and an external currency (USD). @@ -1340,8 +1326,8 @@ pub mod ddc_bucket { /// /// This requires the permission SetExchangeRate or SuperAdmin. #[ink(message)] - pub fn account_set_usd_per_cere(&mut self, usd_per_cere: Balance) { - self.message_account_set_usd_per_cere(usd_per_cere); + pub fn account_set_usd_per_cere(&mut self, usd_per_cere: Balance) -> Result<()> { + self.message_account_set_usd_per_cere(usd_per_cere) } } // ---- End Billing ---- @@ -1600,25 +1586,25 @@ pub mod ddc_bucket { /// /// This is a temporary measure to allow migrating the funds to a new version of the contract. #[ink(message)] - pub fn admin_withdraw(&mut self, amount: Balance) { - self.message_admin_withdraw(amount).unwrap(); + pub fn admin_withdraw(&mut self, amount: Balance) -> Result<()> { + self.message_admin_withdraw(amount) } /// As SuperAdmin, set the network and cluster fee configuration. #[ink(message)] - pub fn admin_set_network_fee_config(&mut self, config: NetworkFeeConfig) { - self.message_admin_set_network_fee_config(config).unwrap(); + pub fn admin_set_network_fee_config(&mut self, config: NetworkFeeConfig) -> Result<()> { + self.message_admin_set_network_fee_config(config) } /// Pay the revenues accumulated by the protocol #[ink(message)] - pub fn admin_withdraw_protocol_revenues(&mut self, amount: u128) -> () { - self.message_withdraw_revenues(amount).unwrap(); + pub fn admin_withdraw_protocol_revenues(&mut self, amount: u128) -> Result<()> { + self.message_withdraw_revenues(amount) } #[ink(message)] - pub fn admin_set_protocol_fee_bp(&mut self, protocol_fee_bp: u128) -> () { - self.message_set_protocol_fee_bp(protocol_fee_bp).unwrap(); + pub fn admin_set_protocol_fee_bp(&mut self, protocol_fee_bp: u128) -> Result<()> { + self.message_set_protocol_fee_bp(protocol_fee_bp) } } @@ -1705,6 +1691,7 @@ pub mod ddc_bucket { TransferFailed, InsufficientBalance, InsufficientResources, + EraSettingFailed } pub type Result = core::result::Result; From d065197c95e5ce20d955fc86b57d14e4069562dd Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Fri, 30 Jun 2023 16:34:41 +0200 Subject: [PATCH 74/89] fix(lib): strict versions for scale derive macro crates and excluding the Cargo.lock from .gitignore --- .gitignore | 4 - Cargo.lock | 787 ++++++++++++++++++++++++++++++++++++++++++++++ bucket/Cargo.toml | 2 + 3 files changed, 789 insertions(+), 4 deletions(-) create mode 100644 Cargo.lock diff --git a/.gitignore b/.gitignore index 2f4d2bfb..de63cccc 100755 --- a/.gitignore +++ b/.gitignore @@ -4,10 +4,6 @@ target # Ignore backup files creates by cargo fmt. **/*.rs.bk -# Remove Cargo.lock when creating an executable, leave it for libraries -# More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock -Cargo.lock - local .idea ink-doc-gen diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..d33dd0d0 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,787 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cpufeatures" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "ddc_bucket" +version = "0.5.2" +dependencies = [ + "ink_allocator", + "ink_env", + "ink_lang", + "ink_lang_codegen", + "ink_lang_ir", + "ink_lang_macro", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage", + "ink_storage_derive", + "more-asserts", + "parity-scale-codec", + "parity-scale-codec-derive", + "scale-info", + "scale-info-derive", + "serde", + "serde_json", +] + +[[package]] +name = "ddc_nft_registry" +version = "0.5.2" +dependencies = [ + "ink_allocator", + "ink_env", + "ink_lang", + "ink_lang_codegen", + "ink_lang_ir", + "ink_lang_macro", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage", + "ink_storage_derive", + "parity-scale-codec", + "scale-info", + "serde", + "serde_json", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "impl-serde" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" +dependencies = [ + "serde", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "ink_allocator" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c9588a59a0e8997c0b2153cd11b5aaa77c06a0537a6b18f3811d1f1aa098b12" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_engine" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487c3b390b7feb0620496b0cd38683433c7d7e6946b1caabda51e1f23eb24b30" +dependencies = [ + "blake2", + "derive_more", + "parity-scale-codec", + "rand", + "secp256k1", + "sha2", + "sha3", +] + +[[package]] +name = "ink_env" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a891d34301a3dbb1c7b7424c49ae184282b163491c54f9acd17fcbe14a80447b" +dependencies = [ + "arrayref", + "blake2", + "cfg-if", + "derive_more", + "ink_allocator", + "ink_engine", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "num-traits", + "parity-scale-codec", + "paste", + "rand", + "rlibc", + "scale-info", + "secp256k1", + "sha2", + "sha3", + "static_assertions", +] + +[[package]] +name = "ink_lang" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cca26e374e0f89c82cf5dabb4309ef3c76a01659ad95186f4e84455c5f4621a0" +dependencies = [ + "derive_more", + "ink_env", + "ink_lang_macro", + "ink_prelude", + "ink_primitives", + "ink_storage", + "parity-scale-codec", +] + +[[package]] +name = "ink_lang_codegen" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fe57826726d89c84fe0b1fafe0dee328f58c8e927be40f0290f04602aacc45c" +dependencies = [ + "blake2", + "derive_more", + "either", + "heck", + "impl-serde", + "ink_lang_ir", + "itertools", + "parity-scale-codec", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ink_lang_ir" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f47d16b2a5340df90f11b2ec2242b37907f5c8396dbbc72c52ec9f2b1a8c90c8" +dependencies = [ + "blake2", + "either", + "itertools", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "ink_lang_macro" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81b858be42ac6cde2c15ce6d7fa75cef59b64a3baf37f7105f39208f2b84dadb" +dependencies = [ + "ink_lang_codegen", + "ink_lang_ir", + "ink_primitives", + "parity-scale-codec", + "proc-macro2", + "syn", +] + +[[package]] +name = "ink_metadata" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74913aaed5751f5615af4631b7559328b8ed56c9cb821b89e14af0706176e849" +dependencies = [ + "derive_more", + "impl-serde", + "ink_prelude", + "ink_primitives", + "scale-info", + "serde", +] + +[[package]] +name = "ink_prelude" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f031e6b8495594a7288b089bf4122e76c26b994959d1b2b693bdfe846b14c0e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ink_primitives" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12cf42dce81d060401c7cec95a392ad6d3c2f18661fa3083f619ce135133c33" +dependencies = [ + "cfg-if", + "ink_prelude", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "ink_storage" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c0a98b6acbd79eedf44720412437d713e7195d1407822604de5885b0ee6c7e1" +dependencies = [ + "array-init", + "cfg-if", + "derive_more", + "ink_env", + "ink_metadata", + "ink_prelude", + "ink_primitives", + "ink_storage_derive", + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "ink_storage_derive" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "babf1d8903dc9219ad8e8aa181eddb919d9794aad1da23ccdce770925b7de2ba" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "libc" +version = "0.2.146" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "more-asserts" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5474f8732dc7e0635ae9df6595bcd39cd30e3cfe8479850d4fa3e69306c19712" + +[[package]] +name = "num-traits" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "parity-scale-codec" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8b44461635bbb1a0300f100a841e571e7d919c81c73075ef5d152ffdb521066" +dependencies = [ + "arrayvec", + "bitvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", + "serde", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c45ed1f39709f5a89338fab50e59816b2e8815f5bb58276e7ddf9afd495f73f8" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "paste" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rlibc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc874b127765f014d792f16763a81245ab80500e2ad921ed4ee9e82481ee08fe" + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "scale-info" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0563970d79bcbf3c537ce3ad36d859b30d36fc5b190efd227f1f7a84d7cf0d42" +dependencies = [ + "bitvec", + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", + "serde", +] + +[[package]] +name = "scale-info-derive" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61fa974aea2d63dd18a4ec3a49d59af9f34178c73a4f56d2f18205628d00681e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "secp256k1" +version = "0.24.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" +dependencies = [ + "secp256k1-sys", +] + +[[package]] +name = "secp256k1-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" +dependencies = [ + "cc", +] + +[[package]] +name = "serde" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.136" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "unicode-xid", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "toml_datetime" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" + +[[package]] +name = "toml_edit" +version = "0.19.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-ident" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winnow" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] diff --git a/bucket/Cargo.toml b/bucket/Cargo.toml index d61440b4..8fc4ab87 100755 --- a/bucket/Cargo.toml +++ b/bucket/Cargo.toml @@ -8,7 +8,9 @@ license = "Apache-2.0" [dependencies] scale = { package = "parity-scale-codec", version = "=3.1.2", default-features = false, features = ["derive"] } +scale-derive = { package = "parity-scale-codec-derive", version = "=3.1.2", default-features = false } scale-info = { version = "=2.0.1", default-features = false, features = ["derive"], optional = true } +scale-info-derive = { version = "=2.5.0", default-features = false, optional = true } ink_primitives = { version = "3.4.0", default-features = false } ink_metadata = { version = "3.4.0", default-features = false, features = ["derive"], optional = true } From d2bc01709a4ff7c3302aa6eec84d49844c44c8e9 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Fri, 30 Jun 2023 19:33:03 +0200 Subject: [PATCH 75/89] fix(scripts): example scripts recovered --- bucket/ddc_bucket/cluster/messages.rs | 18 +- bucket/ddc_bucket/tests/env_utils.rs | 3 +- bucket/ddc_bucket/tests/test_cluster.rs | 2 +- bucket/lib.rs | 47 +- scripts/examples/ddcBucketDemo.js | 232 +- scripts/examples/ddcBucketPrint.js | 12 +- scripts/sdk/src/abi/ddc_bucket.json | 5103 +++++++++++++++-------- scripts/sdk/src/bucket/ddcBucket.js | 132 +- scripts/sdk/src/config/index.js | 3 +- scripts/sdk/src/deploymentRegistry.js | 5 + 10 files changed, 3604 insertions(+), 1953 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index fdfa60e4..2d6a129b 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -13,7 +13,7 @@ use crate::ddc_bucket::ClusterNodeReplaced; use crate::ddc_bucket::{ BASIS_POINTS, AccountId, Balance, ClusterCreated, ClusterNodeAdded, ClusterNodeRemoved, - ClusterCdnNodeAdded, ClusterCdnNodeRemoved, ClusterDistributeRevenues, CdnClusterDistributeRevenues, ClusterReserveResource, + ClusterCdnNodeAdded, ClusterCdnNodeRemoved, ClusterDistributeRevenues, ClusterReserveResource, ClusterDistributeCdnRevenues, ClusterRemoved, ClusterParamsSet, ClusterNodeStatusSet, ClusterCdnNodeStatusSet, PermissionGranted, PermissionRevoked, DdcBucket, NodeStatusInCluster, Result, Error::* }; @@ -39,7 +39,7 @@ impl DdcBucket { Self::env().emit_event(ClusterCreated { cluster_id, - manager: caller, + manager_id: caller, cluster_params, }); @@ -297,14 +297,14 @@ impl DdcBucket { pub fn message_grant_trusted_manager_permission( &mut self, - manager: AccountId + manager_id: AccountId ) -> Result<()> { let grantor = Self::env().caller(); let permission = Permission::ClusterManagerTrustedBy(grantor); - self.grant_permission(manager, permission)?; + self.grant_permission(manager_id, permission)?; Self::env().emit_event(PermissionGranted { - account_id: manager, + account_id: manager_id, permission }); @@ -314,14 +314,14 @@ impl DdcBucket { pub fn message_revoke_trusted_manager_permission( &mut self, - manager: AccountId + manager_id: AccountId ) -> Result<()> { let grantor = Self::env().caller(); let permission = Permission::ClusterManagerTrustedBy(grantor); - self.revoke_permission(manager, permission)?; + self.revoke_permission(manager_id, permission)?; Self::env().emit_event(PermissionRevoked { - account_id: manager, + account_id: manager_id, permission }); @@ -592,7 +592,7 @@ impl DdcBucket { cdn_node.take_payment(cdn_node.undistributed_payment)?; self.cdn_nodes.update(*cdn_node_key, &cdn_node)?; - Self::env().emit_event(CdnClusterDistributeRevenues { + Self::env().emit_event(ClusterDistributeCdnRevenues { cluster_id, provider_id: cdn_node.provider_id }); diff --git a/bucket/ddc_bucket/tests/env_utils.rs b/bucket/ddc_bucket/tests/env_utils.rs index dd44f128..5551e208 100644 --- a/bucket/ddc_bucket/tests/env_utils.rs +++ b/bucket/ddc_bucket/tests/env_utils.rs @@ -69,8 +69,7 @@ pub fn print_events(events: &[Event]) { Event::Deposit(ev) => println!("EVENT {:?}", ev), Event::PermissionGranted(ev) => println!("EVENT {:?}", ev), Event::PermissionRevoked(ev) => println!("EVENT {:?}", ev), - Event::CdnClusterCreated(ev) => println!("EVENT {:?}", ev), - Event::CdnClusterDistributeRevenues(ev) => println!("EVENT {:?}", ev), + Event::ClusterDistributeCdnRevenues(ev) => println!("EVENT {:?}", ev), Event::CdnNodeCreated(ev) => println!("EVENT {:?}", ev), Event::ClusterNodeAdded(ev) => println!("EVENT {:?}", ev), Event::ClusterCdnNodeAdded(ev) => println!("{:?}", ev), diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 570742ba..976ca822 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -188,7 +188,7 @@ fn cluster_create_ok() { matches!(events.pop().unwrap(), Event::ClusterCreated(ev) if ev == ClusterCreated { cluster_id: ctx.cluster_id, - manager: ctx.manager_id, + manager_id: ctx.manager_id, cluster_params: ctx.cluster_params.clone() }) ); diff --git a/bucket/lib.rs b/bucket/lib.rs index f3ce4149..eb5d057e 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -272,7 +272,7 @@ pub mod ddc_bucket { #[ink(topic)] cluster_id: ClusterId, #[ink(topic)] - manager: AccountId, + manager_id: AccountId, cluster_params: ClusterParams, } @@ -377,6 +377,15 @@ pub mod ddc_bucket { provider_id: AccountId, } + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct ClusterDistributeCdnRevenues { + #[ink(topic)] + cluster_id: ClusterId, + #[ink(topic)] + provider_id: AccountId, + } + impl DdcBucket { /// Creates a cluster of Storage nodes and CDN nodes. @@ -832,30 +841,6 @@ pub mod ddc_bucket { } // ---- End Cluster ---- - // ---- CDN Cluster ---- - - /// A new cluster was created. - #[ink(event)] - #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] - pub struct CdnClusterCreated { - #[ink(topic)] - cluster_id: ClusterId, - #[ink(topic)] - manager: AccountId, - } - - /// The respective share of revenues of a CDN cluster for a provider was distributed. - #[ink(event)] - #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] - pub struct CdnClusterDistributeRevenues { - #[ink(topic)] - cluster_id: ClusterId, - #[ink(topic)] - provider_id: AccountId, - } - - // ---- End CDN Cluster ---- - // ---- Committer ---- impl DdcBucket { @@ -1386,7 +1371,7 @@ pub mod ddc_bucket { /// /// # Parameters /// - /// * `manager` - cluster manager account. + /// * `manager_id` - cluster manager account. /// /// # Output /// @@ -1402,9 +1387,9 @@ pub mod ddc_bucket { #[ink(message, payable)] pub fn grant_trusted_manager_permission( &mut self, - manager: AccountId + manager_id: AccountId ) -> Result<()> { - self.message_grant_trusted_manager_permission(manager) + self.message_grant_trusted_manager_permission(manager_id) } /// Revokes permissions from cluster manager. @@ -1415,7 +1400,7 @@ pub mod ddc_bucket { /// /// # Parameters /// - /// * `manager` - cluster manager account. + /// * `manager_id` - cluster manager account. /// /// # Output /// @@ -1431,9 +1416,9 @@ pub mod ddc_bucket { #[ink(message)] pub fn revoke_trusted_manager_permission( &mut self, - manager: AccountId + manager_id: AccountId ) -> Result<()> { - self.message_revoke_trusted_manager_permission(manager) + self.message_revoke_trusted_manager_permission(manager_id) } } diff --git a/scripts/examples/ddcBucketDemo.js b/scripts/examples/ddcBucketDemo.js index 254065c7..b02c6e61 100644 --- a/scripts/examples/ddcBucketDemo.js +++ b/scripts/examples/ddcBucketDemo.js @@ -42,142 +42,254 @@ async function main() { }; // Test data. - const managerId = account.address; + const clusterManagerId = account.address; + const nodePubKey = randomAccount().address; + const cdnNodePubKey = randomAccount().address; + const anyAccountId = account.address; - const rentPerMonth = 10n * CERE; - const nodeParams = "{\"url\":\"https://ddc-123.cere.network/bucket/{BUCKET_ID}\"}"; - const capacity = 1e6; - const vNodes = [1,2,3,4,5,6]; - const clusterResource = 10; + const bucketResource = 5; const bucketParams = "{}"; - const nodePubKey = randomAccount().address; - let nodeId; + let nodeKey; { - log("Setup a node…"); - const tx = bucketContract.tx - .nodeCreate(txOptionsPay, rentPerMonth, nodeParams, capacity, 'ADDING', nodePubKey); + log("Create a Storage node..."); + const nodeParams = "{\"url\":\"https://ddc-123.cere.network/storage/0\"}"; + const capacity = 1e6; + const rentPerMonth = 10n * CERE; + const tx = bucketContract.tx.nodeCreate( + txOptionsPay, + nodePubKey, + nodeParams, + capacity, + rentPerMonth, + ); const result = await sendTx(account, tx); printGas(result); log(getExplorerUrl(result)); const events = printEvents(result); - nodeId = ddcBucket.findCreatedNodeId(events); - log("New NodeId", nodeId, "\n"); + let event = ddcBucket.findNodeCreatedEvent(events); + nodeKey = event.nodeKey; + log("NodeCreated", event, "\n"); } - + + let cdnNodeKey; { - log("Trust the cluster manager…"); - const tx = bucketContract.tx - .nodeTrustManager(txOptionsPay, managerId); + log("Create a CDN node..."); + const cdnNodeParams = "{\"url\":\"https://ddc-123.cere.network/cdn/0\"}"; + const tx = bucketContract.tx.cdnNodeCreate( + txOptionsPay, + cdnNodePubKey, + cdnNodeParams + ); const result = await sendTx(account, tx); printGas(result); log(getExplorerUrl(result)); - printEvents(result); - log(); + const events = printEvents(result); + let event = ddcBucket.findCdnNodeCreatedEvent(events); + cdnNodeKey = event.cdnNodeKey; + log("CdnNodeCreated", event, "\n"); } let clusterId; { - log("Setup a cluster…"); + log("Setup a cluster..."); let clusterParams = "{}"; - const tx = bucketContract.tx - .clusterCreate(txOptionsPay, managerId, vNodes, [nodeId], clusterParams); + const tx = bucketContract.tx.clusterCreate( + txOptionsPay, + clusterParams + ); const result = await sendTx(account, tx); printGas(result); log(getExplorerUrl(result)); const events = printEvents(result); - clusterId = ddcBucket.findCreatedClusterId(events); - log("New ClusterId", clusterId, "\n"); + let event = ddcBucket.findClusterCreatedEvent(events); + clusterId = event.clusterId; + log("ClusterCreated", event, "\n"); + } + + let trustedManagerId; + { + log("Trust the cluster manager..."); + const tx = bucketContract.tx.grantTrustedManagerPermission( + txOptionsPay, + clusterManagerId + ); + const result = await sendTx(account, tx); + printGas(result); + log(getExplorerUrl(result)); + const events = printEvents(result); + let event = ddcBucket.findPermissionGrantedEvent(events); + trustedManagerId = event.accountId; + log("PermissionGranted", event, "\n"); } { - log("Reserve some resources for the cluster…"); - const tx = bucketContract.tx - .clusterReserveResource(txOptions, clusterId, clusterResource); + log("Adding Storage node to the cluster..."); + const vNodes = [1,2,3,4,5,6]; + const tx = bucketContract.tx.clusterAddNode( + txOptionsPay, + clusterId, + nodeKey, + vNodes + ); const result = await sendTx(account, tx); printGas(result); log(getExplorerUrl(result)); - printEvents(result); - log(); + const events = printEvents(result); + let event = ddcBucket.findClusterNodeAddedEvent(events); + log("ClusterNodeAdded", event, "\n"); } { - log("Changing node tag…"); - const tx = bucketContract.tx - .clusterChangeNodeTag(txOptions, nodeId, 'ACTIVE'); + log("Adding CDN node to the cluster..."); + const tx = bucketContract.tx.clusterAddCdnNode( + txOptionsPay, + clusterId, + cdnNodeKey, + ); const result = await sendTx(account, tx); printGas(result); log(getExplorerUrl(result)); - printEvents(result); - log(); + const events = printEvents(result); + let event = ddcBucket.findClusterCdnNodeAddedEvent(events); + cdnNodeKey = event.cdnNodeKey; + log("ClusterCdnNodeAdded", event, "\n"); + } + + { + log("Reserve some resources for the cluster..."); + const clusterResource = 10; + const tx = bucketContract.tx.clusterReserveResource( + txOptions, + clusterId, + clusterResource + ); + + const result = await sendTx(account, tx); + printGas(result); + log(getExplorerUrl(result)); + const events = printEvents(result); + let event = ddcBucket.findClusterReserveResourceEvent(events); + log("ClusterReserveResource", event, "\n"); + } + + { + log("Changing Storage node status..."); + const tx = bucketContract.tx.clusterSetNodeStatus( + txOptions, + clusterId, + nodeKey, + 'ACTIVE' + ); + + const result = await sendTx(account, tx); + printGas(result); + log(getExplorerUrl(result)); + const events = printEvents(result); + let event = ddcBucket.findClusterNodeStatusSetEvent(events); + log("ClusterNodeStatusSet", event, "\n"); + } + + { + log("Changing CDN node status..."); + const tx = bucketContract.tx.clusterSetCdnNodeStatus( + txOptions, + clusterId, + cdnNodeKey, + 'ACTIVE' + ); + + const result = await sendTx(account, tx); + printGas(result); + log(getExplorerUrl(result)); + const events = printEvents(result); + let event = ddcBucket.findClusterCdnNodeStatusSetEvent(events); + log("ClusterCdnNodeStatusSet", event, "\n"); } let bucketId; { - log("Create a bucket…"); - const tx = bucketContract.tx - .bucketCreate(txOptionsPay, bucketParams, clusterId, null); + log("Create a bucket..."); + const tx = bucketContract.tx.bucketCreate( + txOptionsPay, + bucketParams, + clusterId, + null + ); const result = await sendTx(account, tx); printGas(result); log(getExplorerUrl(result)); const events = printEvents(result); - bucketId = ddcBucket.findCreatedBucketId(events); - log("New BucketId", bucketId, "\n"); + let event = ddcBucket.findBucketCreatedEvent(events); + bucketId = event.bucketId; + log("BucketCreated", event, "\n"); } { - log("Topup the account…"); - const tx = bucketContract.tx - .accountDeposit(txOptionsPay); + log("Topup the account..."); + const tx = bucketContract.tx.accountDeposit( + txOptionsPay + ); const result = await sendTx(account, tx); printGas(result); log(getExplorerUrl(result)); - printEvents(result); - log(); + const events = printEvents(result); + let event = ddcBucket.findDepositEvent(events); + log("Deposit", event, "\n"); } { - log("Allocate some resources for the bucket…"); - const tx = bucketContract.tx - .bucketAllocIntoCluster(txOptions, bucketId, bucketResource); + log("Allocate some resources for the bucket..."); + const tx = bucketContract.tx.bucketAllocIntoCluster( + txOptions, + bucketId, + bucketResource + ); const result = await sendTx(account, tx); printGas(result); log(getExplorerUrl(result)); - printEvents(result); - log(); + const events = printEvents(result); + let event = ddcBucket.findBucketAllocatedEvent(events); + log("BucketAllocated", event, "\n"); } { - log("Collect payment from Bucket to Cluster…"); - const tx = bucketContract.tx - .bucketSettlePayment(txOptions, bucketId); + log("Collect payment from Bucket to Cluster..."); + const tx = bucketContract.tx.bucketSettlePayment( + txOptions, + bucketId + ); const result = await sendTx(account, tx); printGas(result); log(getExplorerUrl(result)); - printEvents(result); - log(); + const events = printEvents(result); + let event = ddcBucket.findBucketSettlePaymentEvent(events) + log("BucketSettlePayment", event, "\n"); } { - log("Distribute payment from Cluster to Providers…"); - const tx = bucketContract.tx - .clusterDistributeRevenues(txOptions, clusterId); + log("Distribute payment from Cluster to Providers..."); + const tx = bucketContract.tx.clusterDistributeRevenues( + txOptions, + clusterId + ); const result = await sendTx(account, tx); printGas(result); log(getExplorerUrl(result)); - printEvents(result); - log(); + const events = printEvents(result); + let event = ddcBucket.findClusterDistributeRevenuesEvent(events); + log("ClusterDistributeRevenues", event, "\n"); } log(" ---- \n"); @@ -185,7 +297,7 @@ async function main() { { log("Read the node status…"); const {result, output} = await bucketContract.query - .nodeGet(anyAccountId, txOptions, nodeId); + .nodeGet(anyAccountId, txOptions, nodeKey); if (!result.isOk) assert.fail(result.asErr); log("Node", output.toHuman(), "\n"); diff --git a/scripts/examples/ddcBucketPrint.js b/scripts/examples/ddcBucketPrint.js index ea6f98b5..2558f333 100644 --- a/scripts/examples/ddcBucketPrint.js +++ b/scripts/examples/ddcBucketPrint.js @@ -108,17 +108,17 @@ function printGraph(clusters, nodes, buckets) { log(); for (status of nodes) { - let {nodeId, node} = status; + let {nodeKey, node} = status; // Define - log(`Node_${nodeId}[(Node ${nodeId})]`); + log(`Node_${nodeKey}[(Node ${nodeKey})]`); // Node to Provider. - log(`Node_${nodeId} -. owned by .-> Account_${node.providerId.substr(0, 8)}`); + log(`Node_${nodeKey} -. owned by .-> Account_${node.providerId.substr(0, 8)}`); log(); } for (status of clusters) { - let {clusterId, cluster} = status; + let {clusterId, cluster, clusterVNodes} = status; // Define log(`Cluster_${clusterId}((Cluster ${clusterId}))`); @@ -126,8 +126,8 @@ function printGraph(clusters, nodes, buckets) { log(`Cluster_${clusterId} -. managed by ..-> Account_${cluster.managerId.substr(0, 8)}`); // Cluster to Node. - for (i = 0; i < cluster.vNodes.length; i++) { - let vNodeId = cluster.vNodes[i]; + for (i = 0; i < clusterVNodes.length; i++) { + let vNodeId = clusterVNodes[i]; log(`Cluster_${clusterId} -- P${i} --> Node_${vNodeId}`); } log(); diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index 956a7ee5..fefd6892 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -1,6 +1,6 @@ { "source": { - "hash": "0x74f1167a7247be04958655c6d3cfdee21a73146f183cabd7964ddddb5aaec722", + "hash": "0xcc988ca917fa8ca03d34e33ee0ce905a8e494ac4d412367588c110ceeb5cd1b3", "language": "ink! 3.4.0", "compiler": "rustc 1.69.0-nightly" }, @@ -40,7 +40,7 @@ "displayName": [ "BucketId" ], - "type": 5 + "type": 6 } }, { @@ -51,7 +51,7 @@ "displayName": [ "AccountId" ], - "type": 2 + "type": 9 } } ], @@ -70,7 +70,7 @@ "displayName": [ "BucketId" ], - "type": 5 + "type": 6 } }, { @@ -81,7 +81,7 @@ "displayName": [ "ClusterId" ], - "type": 5 + "type": 6 } }, { @@ -92,7 +92,7 @@ "displayName": [ "Resource" ], - "type": 5 + "type": 6 } } ], @@ -111,7 +111,7 @@ "displayName": [ "BucketId" ], - "type": 5 + "type": 6 } }, { @@ -122,7 +122,7 @@ "displayName": [ "ClusterId" ], - "type": 5 + "type": 6 } } ], @@ -141,7 +141,7 @@ "displayName": [ "BucketId" ], - "type": 5 + "type": 6 } }, { @@ -152,7 +152,7 @@ "displayName": [ "bool" ], - "type": 9 + "type": 3 } } ], @@ -161,6 +161,34 @@ ], "label": "BucketAvailabilityUpdated" }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 6 + } + }, + { + "docs": [], + "indexed": false, + "label": "bucket_params", + "type": { + "displayName": [ + "BucketParams" + ], + "type": 13 + } + } + ], + "docs": [], + "label": "BucketParamsSet" + }, { "args": [ { @@ -171,7 +199,7 @@ "displayName": [ "ClusterId" ], - "type": 5 + "type": 6 } }, { @@ -182,7 +210,7 @@ "displayName": [ "AccountId" ], - "type": 2 + "type": 9 } }, { @@ -193,13 +221,11 @@ "displayName": [ "ClusterParams" ], - "type": 14 + "type": 13 } } ], - "docs": [ - " A new cluster was created." - ], + "docs": [], "label": "ClusterCreated" }, { @@ -212,7 +238,7 @@ "displayName": [ "ClusterId" ], - "type": 5 + "type": 6 } }, { @@ -223,14 +249,12 @@ "displayName": [ "NodeKey" ], - "type": 2 + "type": 9 } } ], - "docs": [ - " A vnode was re-assigned to new node." - ], - "label": "ClusterNodeReplaced" + "docs": [], + "label": "ClusterNodeAdded" }, { "args": [ @@ -242,25 +266,23 @@ "displayName": [ "ClusterId" ], - "type": 5 + "type": 6 } }, { "docs": [], - "indexed": false, - "label": "resource", + "indexed": true, + "label": "node_key", "type": { "displayName": [ - "Resource" + "NodeKey" ], - "type": 5 + "type": 9 } } ], - "docs": [ - " Some resources were reserved for the cluster from the nodes." - ], - "label": "ClusterReserveResource" + "docs": [], + "label": "ClusterNodeRemoved" }, { "args": [ @@ -272,25 +294,23 @@ "displayName": [ "ClusterId" ], - "type": 5 + "type": 6 } }, { "docs": [], "indexed": true, - "label": "provider_id", + "label": "cdn_node_key", "type": { "displayName": [ - "AccountId" + "CdnNodeKey" ], - "type": 2 + "type": 9 } } ], - "docs": [ - " The share of revenues of a cluster for a provider was distributed." - ], - "label": "ClusterDistributeRevenues" + "docs": [], + "label": "ClusterCdnNodeAdded" }, { "args": [ @@ -302,25 +322,23 @@ "displayName": [ "ClusterId" ], - "type": 5 + "type": 6 } }, { "docs": [], "indexed": true, - "label": "manager", + "label": "cdn_node_key", "type": { "displayName": [ - "AccountId" + "CdnNodeKey" ], - "type": 2 + "type": 9 } } ], - "docs": [ - " A new cluster was created." - ], - "label": "CdnClusterCreated" + "docs": [], + "label": "ClusterCdnNodeRemoved" }, { "args": [ @@ -332,712 +350,660 @@ "displayName": [ "ClusterId" ], - "type": 5 + "type": 6 } }, { "docs": [], - "indexed": true, - "label": "provider_id", + "indexed": false, + "label": "cluster_params", "type": { "displayName": [ - "AccountId" + "ClusterParams" ], - "type": 2 + "type": 13 } } ], - "docs": [ - " The respective share of revenues of a CDN cluster for a provider was distributed." - ], - "label": "CdnClusterDistributeRevenues" + "docs": [], + "label": "ClusterParamsSet" }, { "args": [ { "docs": [], "indexed": true, - "label": "cdn_node_key", + "label": "cluster_id", "type": { "displayName": [ - "CdnNodeKey" + "ClusterId" ], - "type": 2 + "type": 6 } - }, + } + ], + "docs": [], + "label": "ClusterRemoved" + }, + { + "args": [ { "docs": [], "indexed": true, - "label": "provider_id", + "label": "node_key", "type": { "displayName": [ - "AccountId" + "NodeKey" ], - "type": 2 + "type": 9 } }, { "docs": [], - "indexed": false, - "label": "cdn_node_params", + "indexed": true, + "label": "cluster_id", "type": { "displayName": [ - "CdnNodeParams" + "ClusterId" ], - "type": 14 + "type": 6 } }, { "docs": [], "indexed": false, - "label": "undistributed_payment", + "label": "status", "type": { "displayName": [ - "Balance" + "NodeStatusInCluster" ], - "type": 8 + "type": 23 } } ], - "docs": [ - " A node was created. The given account is its owner and recipient of revenues." - ], - "label": "CdnNodeCreated" + "docs": [], + "label": "ClusterNodeStatusSet" }, { "args": [ { "docs": [], "indexed": true, - "label": "node_key", + "label": "cdn_node_key", "type": { "displayName": [ - "NodeKey" + "CdnNodeKey" ], - "type": 2 + "type": 9 } }, { "docs": [], "indexed": true, - "label": "provider_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 2 - } - }, - { - "docs": [], - "indexed": false, - "label": "rent_per_month", + "label": "cluster_id", "type": { "displayName": [ - "Balance" + "ClusterId" ], - "type": 8 + "type": 6 } }, { "docs": [], "indexed": false, - "label": "node_params", + "label": "status", "type": { "displayName": [ - "NodeParams" + "NodeStatusInCluster" ], - "type": 14 + "type": 23 } } ], - "docs": [ - " A node was created. The given account is its owner and recipient of revenues." - ], - "label": "NodeCreated" + "docs": [], + "label": "ClusterCdnNodeStatusSet" }, { "args": [ { "docs": [], "indexed": true, - "label": "account_id", + "label": "cluster_id", "type": { "displayName": [ - "AccountId" + "ClusterId" ], - "type": 2 + "type": 6 } }, { "docs": [], - "indexed": false, - "label": "value", + "indexed": true, + "label": "node_key", "type": { "displayName": [ - "Balance" + "NodeKey" ], - "type": 8 + "type": 9 } } ], "docs": [ - " Tokens were deposited on an account." + " A vnode was re-assigned to new node." ], - "label": "Deposit" + "label": "ClusterNodeReplaced" }, { "args": [ { "docs": [], "indexed": true, - "label": "account_id", + "label": "cluster_id", "type": { "displayName": [ - "AccountId" + "ClusterId" ], - "type": 2 + "type": 6 } }, { "docs": [], "indexed": false, - "label": "permission", + "label": "resource", "type": { "displayName": [ - "Permission" + "Resource" ], - "type": 74 + "type": 6 } } ], "docs": [ - " A permission was granted to the account." + " Some resources were reserved for the cluster from the nodes." ], - "label": "PermissionGranted" + "label": "ClusterReserveResource" }, { "args": [ { "docs": [], "indexed": true, - "label": "account_id", + "label": "cluster_id", "type": { "displayName": [ - "AccountId" + "ClusterId" ], - "type": 2 + "type": 6 } }, { "docs": [], - "indexed": false, - "label": "permission", + "indexed": true, + "label": "provider_id", "type": { "displayName": [ - "Permission" + "AccountId" ], - "type": 74 + "type": 9 } } ], "docs": [ - " A permission was revoked from the account." + " The share of revenues of a cluster for a provider was distributed." ], - "label": "PermissionRevoked" - } - ], - "messages": [ + "label": "ClusterDistributeRevenues" + }, { "args": [ { - "label": "bucket_params", - "type": { - "displayName": [ - "BucketParams" - ], - "type": 14 - } - }, - { + "docs": [], + "indexed": true, "label": "cluster_id", "type": { "displayName": [ "ClusterId" ], - "type": 5 + "type": 6 } }, { - "label": "owner_id", + "docs": [], + "indexed": true, + "label": "manager", "type": { "displayName": [ - "Option" + "AccountId" ], - "type": 41 + "type": 9 } } ], "docs": [ - " Create a new bucket and return its `bucket_id`.", - "", - " The caller will be its first owner and payer of resources.", - "", - " `bucket_params` is configuration used by clients and nodes. See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema)", - "", - " The bucket can be connected to a single cluster (currently). Allocate cluster resources with the function `bucket_alloc_into_cluster`" + " A new cluster was created." ], - "label": "bucket_create", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [ - "BucketId" - ], - "type": 5 - }, - "selector": "0x0aeb2379" + "label": "CdnClusterCreated" }, { "args": [ { - "label": "bucket_id", + "docs": [], + "indexed": true, + "label": "cluster_id", "type": { "displayName": [ - "BucketId" + "ClusterId" ], - "type": 5 + "type": 6 } }, { - "label": "owner_id", + "docs": [], + "indexed": true, + "label": "provider_id", "type": { "displayName": [ "AccountId" ], - "type": 2 + "type": 9 } } ], "docs": [ - " Change owner of the bucket", - "", - " Provide the account of new owner" + " The respective share of revenues of a CDN cluster for a provider was distributed." ], - "label": "bucket_change_owner", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [], - "type": 42 - }, - "selector": "0xc7d0c2cd" + "label": "CdnClusterDistributeRevenues" }, { "args": [ { - "label": "bucket_id", + "docs": [], + "indexed": true, + "label": "cdn_node_key", "type": { "displayName": [ - "BucketId" + "CdnNodeKey" ], - "type": 5 + "type": 9 } }, { - "label": "resource", + "docs": [], + "indexed": true, + "label": "provider_id", "type": { "displayName": [ - "Resource" + "AccountId" ], - "type": 5 + "type": 9 } - } - ], - "docs": [ - " Allocate some resources of a cluster to a bucket.", - "", - " The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes)." + }, + { + "docs": [], + "indexed": false, + "label": "cdn_node_params", + "type": { + "displayName": [ + "CdnNodeParams" + ], + "type": 13 + } + }, + { + "docs": [], + "indexed": false, + "label": "undistributed_payment", + "type": { + "displayName": [ + "Balance" + ], + "type": 12 + } + } ], - "label": "bucket_alloc_into_cluster", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 42 - }, - "selector": "0x4c482d19" + "docs": [ + " A node was created. The given account is its owner and recipient of revenues." + ], + "label": "CdnNodeCreated" }, { "args": [ { - "label": "bucket_id", + "docs": [], + "indexed": true, + "label": "cdn_node_key", "type": { "displayName": [ - "BucketId" + "CdnNodeKey" ], - "type": 5 + "type": 9 } } ], - "docs": [ - " Settle the due costs of a bucket from its payer account to the cluster account." - ], - "label": "bucket_settle_payment", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0x15974555" + "docs": [], + "label": "CdnNodeRemoved" }, { "args": [ { - "label": "bucket_id", + "docs": [], + "indexed": true, + "label": "cdn_node_key", "type": { "displayName": [ - "BucketId" + "CdnNodeKey" ], - "type": 5 + "type": 9 } }, { - "label": "params", + "docs": [], + "indexed": false, + "label": "cdn_node_params", "type": { "displayName": [ - "BucketParams" + "CdnNodeParams" ], - "type": 14 + "type": 13 } } ], - "docs": [ - " Change the `bucket_params`, which is configuration used by clients and nodes.", - "", - " See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "bucket_change_params", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x9f2d075b" + "docs": [], + "label": "CdnNodeParamsSet" }, { "args": [ { - "label": "bucket_id", + "docs": [], + "indexed": true, + "label": "node_key", "type": { "displayName": [ - "BucketId" + "NodeKey" ], - "type": 5 + "type": 9 } - } - ], - "docs": [ - " Get the current status of a bucket." - ], - "label": "bucket_get", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 43 - }, - "selector": "0x3802cb77" - }, - { - "args": [ + }, { - "label": "offset", + "docs": [], + "indexed": true, + "label": "provider_id", "type": { "displayName": [ - "u32" + "AccountId" ], - "type": 5 + "type": 9 } }, { - "label": "limit", + "docs": [], + "indexed": false, + "label": "rent_per_month", "type": { "displayName": [ - "u32" + "Balance" ], - "type": 5 + "type": 12 } }, { - "label": "filter_owner_id", + "docs": [], + "indexed": false, + "label": "node_params", "type": { "displayName": [ - "Option" + "NodeParams" ], - "type": 41 + "type": 13 } } ], "docs": [ - " Iterate through all buckets.", - "", - " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", - " The optimal `limit` depends on the size of params.", - "", - " The results can be filtered by owner. Note that paging must still be completed fully." + " A node was created. The given account is its owner and recipient of revenues." ], - "label": "bucket_list", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [], - "type": 47 - }, - "selector": "0x417ab584" + "label": "NodeCreated" }, { "args": [ { - "label": "owner_id", + "docs": [], + "indexed": true, + "label": "node_key", "type": { "displayName": [ - "AccountId" + "NodeKey" ], - "type": 2 + "type": 9 } } ], - "docs": [ - " Iterate through all buckets and return only those owned by owner", - "", - " This method returns bucket struct, not the status" - ], - "label": "bucket_list_for_account", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Vec" - ], - "type": 0 - }, - "selector": "0xc434cf57" + "docs": [], + "label": "NodeRemoved" }, { "args": [ { - "label": "bucket_id", + "docs": [], + "indexed": true, + "label": "node_key", "type": { "displayName": [ - "BucketId" + "NodeKey" ], - "type": 5 + "type": 9 } }, { - "label": "public_availability", + "docs": [], + "indexed": false, + "label": "node_params", "type": { "displayName": [ - "bool" + "NodeParams" ], - "type": 9 + "type": 13 } } ], - "docs": [ - " Set availiablity of the bucket" - ], - "label": "bucket_set_availability", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 42 - }, - "selector": "0x053eb3ce" + "docs": [], + "label": "NodeParamsSet" }, { "args": [ { - "label": "bucket_id", + "docs": [], + "indexed": true, + "label": "account_id", "type": { "displayName": [ - "BucketId" + "AccountId" ], - "type": 5 + "type": 9 } }, { - "label": "new_resource_cap", + "docs": [], + "indexed": false, + "label": "value", "type": { "displayName": [ - "Resource" + "Balance" ], - "type": 5 + "type": 12 } } ], "docs": [ - " Set max resource cap to be charged by CDN for public bucket" + " Tokens were deposited on an account." ], - "label": "bucket_set_resource_cap", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 42 - }, - "selector": "0x85010c6d" + "label": "Deposit" }, { "args": [ { - "label": "bucket_id", + "docs": [], + "indexed": true, + "label": "account_id", "type": { "displayName": [ - "BucketId" + "AccountId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": false, + "label": "permission", + "type": { + "displayName": [ + "Permission" ], - "type": 5 + "type": 74 } } ], "docs": [ - " Set permission for the reader of the bucket" + " A permission was granted to the account." ], - "label": "get_bucket_writers", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [ - "Vec" - ], - "type": 11 - }, - "selector": "0x499cd4b7" + "label": "PermissionGranted" }, { "args": [ { - "label": "bucket_id", + "docs": [], + "indexed": true, + "label": "account_id", "type": { "displayName": [ - "BucketId" + "AccountId" ], - "type": 5 + "type": 9 } }, { - "label": "writer", + "docs": [], + "indexed": false, + "label": "permission", "type": { "displayName": [ - "AccountId" + "Permission" ], - "type": 2 + "type": 74 } } ], "docs": [ - " Set permission for the writer of the bucket" + " A permission was revoked from the account." ], - "label": "bucket_set_writer_perm", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 42 - }, - "selector": "0xea2e477a" + "label": "PermissionRevoked" }, { "args": [ { - "label": "bucket_id", + "docs": [], + "indexed": true, + "label": "account_id", "type": { "displayName": [ - "BucketId" + "AccountId" ], - "type": 5 + "type": 9 } }, { - "label": "writer", + "docs": [], + "indexed": true, + "label": "node_key", "type": { "displayName": [ - "AccountId" + "NodeKey" ], - "type": 2 + "type": 9 } } ], - "docs": [ - " Revoke permission for the writer of the bucket" - ], - "label": "bucket_revoke_writer_perm", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 42 - }, - "selector": "0x2b3d8dd1" + "docs": [], + "label": "NodeOwnershipTransferred" }, { "args": [ { - "label": "bucket_id", + "docs": [], + "indexed": true, + "label": "account_id", "type": { "displayName": [ - "BucketId" + "AccountId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": true, + "label": "cdn_node_key", + "type": { + "displayName": [ + "CdnNodeKey" ], - "type": 5 + "type": 9 } } ], - "docs": [ - " Set permission for the reader of the bucket" - ], - "label": "get_bucket_readers", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [ - "Vec" - ], - "type": 11 - }, - "selector": "0xb9a7cc1c" - }, + "docs": [], + "label": "CdnNodeOwnershipTransferred" + } + ], + "messages": [ { "args": [ { - "label": "bucket_id", + "label": "bucket_params", "type": { "displayName": [ - "BucketId" + "BucketParams" ], - "type": 5 + "type": 13 } }, { - "label": "reader", + "label": "cluster_id", "type": { "displayName": [ - "AccountId" + "ClusterId" + ], + "type": 6 + } + }, + { + "label": "owner_id", + "type": { + "displayName": [ + "Option" ], - "type": 2 + "type": 41 } } ], "docs": [ - " Set permission for the reader of the bucket" + " Create a new bucket and return its `bucket_id`.", + "", + " The caller will be its first owner and payer of resources.", + "", + " `bucket_params` is configuration used by clients and nodes. See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema)", + "", + " The bucket can be connected to a single cluster (currently). Allocate cluster resources with the function `bucket_alloc_into_cluster`" ], - "label": "bucket_set_reader_perm", + "label": "bucket_create", "mutates": true, - "payable": false, + "payable": true, "returnType": { - "displayName": [], + "displayName": [ + "Result" + ], "type": 42 }, - "selector": "0xfc0e94ea" + "selector": "0x0aeb2379" }, { "args": [ @@ -1047,441 +1013,542 @@ "displayName": [ "BucketId" ], - "type": 5 + "type": 6 } }, { - "label": "writer", + "label": "owner_id", "type": { "displayName": [ "AccountId" ], - "type": 2 + "type": 9 } } ], "docs": [ - " Revoke permission for the reader of the bucket" + " Change owner of the bucket", + "", + " Provide the account of new owner" ], - "label": "bucket_revoke_reader_perm", + "label": "bucket_change_owner", "mutates": true, - "payable": false, + "payable": true, "returnType": { - "displayName": [], - "type": 42 + "displayName": [ + "Result" + ], + "type": 44 }, - "selector": "0xe9bfed5a" + "selector": "0xc7d0c2cd" }, { "args": [ { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 5 - } - }, - { - "label": "nodes_keys", + "label": "bucket_id", "type": { "displayName": [ - "Vec" + "BucketId" ], - "type": 11 + "type": 6 } }, { - "label": "v_nodes", + "label": "resource", "type": { "displayName": [ - "Vec" + "Resource" ], - "type": 18 + "type": 6 } } ], "docs": [ - " Removes a set of Storage nodes from an existing cluster", - "", - " The index of virtual nodes in the `v_nodes` param must be aligned with the corresponding physical Storage node in the `nodes_keys` param", + " Allocate some resources of a cluster to a bucket.", "", - " The caller must be its manager" + " The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes)." ], - "label": "cluster_remove_node", + "label": "bucket_alloc_into_cluster", "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x793e0778" + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x4c482d19" }, { "args": [ { - "label": "cluster_id", + "label": "bucket_id", "type": { "displayName": [ - "ClusterId" + "BucketId" ], - "type": 5 + "type": 6 } - }, + } + ], + "docs": [ + " Settle the due costs of a bucket from its payer account to the cluster account." + ], + "label": "bucket_settle_payment", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x15974555" + }, + { + "args": [ { - "label": "node_keys", + "label": "bucket_id", "type": { "displayName": [ - "Vec" + "BucketId" ], - "type": 11 + "type": 6 } }, { - "label": "v_nodes", + "label": "params", "type": { "displayName": [ - "Vec" + "BucketParams" ], - "type": 18 + "type": 13 } } ], "docs": [ - " Adds a set of Storage nodes to an existing cluster", + " Change the `bucket_params`, which is configuration used by clients and nodes.", "", - " The caller must be its manager" + " See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" ], - "label": "cluster_add_node", + "label": "bucket_change_params", "mutates": true, "payable": true, - "returnType": null, - "selector": "0xf7496bdc" + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x9f2d075b" }, { "args": [ { - "label": "nodes_keys", + "label": "bucket_id", "type": { "displayName": [ - "Vec" + "BucketId" ], - "type": 11 + "type": 6 } - }, + } + ], + "docs": [ + " Get the current status of a bucket." + ], + "label": "bucket_get", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 46 + }, + "selector": "0x3802cb77" + }, + { + "args": [ { - "label": "v_nodes", + "label": "offset", "type": { "displayName": [ - "Vec" + "u32" ], - "type": 18 + "type": 6 } }, { - "label": "cdn_nodes_keys", + "label": "limit", "type": { "displayName": [ - "Vec" + "u32" ], - "type": 11 + "type": 6 } }, { - "label": "cluster_params", + "label": "filter_owner_id", "type": { "displayName": [ - "ClusterParams" + "Option" ], - "type": 14 + "type": 41 } } ], "docs": [ - " Creates a new cluster and returns its `cluster_id`.", - "", - " The caller will be its first manager.", + " Iterate through all buckets.", "", - " The cluster can contain both Storage and CDN nodes. The `v_nodes` are assigned to the given Storage physical nodes in a round-robin. Only nodes of providers that trust the cluster manager can be used (see `node_trust_manager`). The assignment can be changed with the function `cluster_replace_node`.", + " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", + " The optimal `limit` depends on the size of params.", "", - " `cluster_params` is configuration used by clients and nodes. In particular, this describes the semantics of vnodes. See the [data structure of ClusterParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" + " The results can be filtered by owner. Note that paging must still be completed fully." ], - "label": "cluster_create", - "mutates": true, - "payable": true, + "label": "bucket_list", + "mutates": false, + "payable": false, "returnType": { - "displayName": [ - "ClusterId" - ], - "type": 5 + "displayName": [], + "type": 49 }, - "selector": "0x4c0f21f6" + "selector": "0x417ab584" }, { "args": [ { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 5 - } - }, - { - "label": "amount", + "label": "owner_id", "type": { "displayName": [ - "Resource" + "AccountId" ], - "type": 5 + "type": 9 } } ], "docs": [ - " As manager, reserve more resources for the cluster from the free capacity of nodes.", + " Iterate through all buckets and return only those owned by owner", "", - " The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes)." + " This method returns bucket struct, not the status" ], - "label": "cluster_reserve_resource", - "mutates": true, + "label": "bucket_list_for_account", + "mutates": false, "payable": false, "returnType": { - "displayName": [], - "type": 42 + "displayName": [ + "Vec" + ], + "type": 51 }, - "selector": "0xb5e38125" + "selector": "0xc434cf57" }, { "args": [ { - "label": "node_key", + "label": "bucket_id", "type": { "displayName": [ - "NodeKey" + "BucketId" ], - "type": 2 + "type": 6 } }, { - "label": "new_tag", + "label": "public_availability", "type": { "displayName": [ - "NodeStatusInCluster" + "bool" ], - "type": 27 + "type": 3 } } ], "docs": [ - " As manager, change a node tag" + " Set availiablity of the bucket" ], - "label": "cluster_change_node_tag", + "label": "bucket_set_availability", "mutates": true, "payable": false, "returnType": { - "displayName": [], - "type": 42 + "displayName": [ + "Result" + ], + "type": 44 }, - "selector": "0x9640d48e" + "selector": "0x053eb3ce" }, { "args": [ { - "label": "cluster_id", + "label": "bucket_id", "type": { "displayName": [ - "ClusterId" + "BucketId" ], - "type": 5 + "type": 6 } }, { - "label": "v_nodes", + "label": "new_resource_cap", "type": { "displayName": [ - "Vec" + "Resource" ], - "type": 19 + "type": 6 } - }, + } + ], + "docs": [ + " Set max resource cap to be charged by CDN for public bucket" + ], + "label": "bucket_set_resource_cap", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x85010c6d" + }, + { + "args": [ { - "label": "new_node_key", + "label": "bucket_id", "type": { "displayName": [ - "NodeKey" + "BucketId" ], - "type": 2 + "type": 6 } } ], "docs": [ - " As manager, re-assign a vnode to another physical node.", - "", - " The cluster manager can only use nodes of providers that trust him (see `node_trust_manager`), or any nodes if he is also SuperAdmin." + " Set permission for the reader of the bucket" ], - "label": "cluster_replace_node", + "label": "get_bucket_writers", "mutates": true, "payable": false, "returnType": { - "displayName": [], - "type": 42 + "displayName": [ + "Vec" + ], + "type": 15 }, - "selector": "0x48194ab1" + "selector": "0x499cd4b7" }, { "args": [ { - "label": "cluster_id", + "label": "bucket_id", "type": { "displayName": [ - "ClusterId" + "BucketId" + ], + "type": 6 + } + }, + { + "label": "writer", + "type": { + "displayName": [ + "AccountId" ], - "type": 5 + "type": 9 } } ], "docs": [ - " Trigger the distribution of revenues from the cluster to the providers." + " Set permission for the writer of the bucket" ], - "label": "cluster_distribute_revenues", + "label": "bucket_set_writer_perm", "mutates": true, "payable": false, - "returnType": null, - "selector": "0xe71e66fc" + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0xea2e477a" }, { "args": [ { - "label": "cluster_id", + "label": "bucket_id", "type": { "displayName": [ - "ClusterId" + "BucketId" ], - "type": 5 + "type": 6 } }, { - "label": "params", + "label": "writer", "type": { "displayName": [ - "ClusterParams" + "AccountId" ], - "type": 14 + "type": 9 } } ], "docs": [ - " Change the `cluster_params`, which is configuration used by clients and nodes.", - "", - " See the [data structure of ClusterParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" + " Revoke permission for the writer of the bucket" ], - "label": "cluster_change_params", + "label": "bucket_revoke_writer_perm", "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x1207912c" + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x2b3d8dd1" }, { "args": [ { - "label": "cluster_id", + "label": "bucket_id", "type": { "displayName": [ - "ClusterId" + "BucketId" ], - "type": 5 + "type": 6 } } ], "docs": [ - " Get the current status of a cluster." + " Set permission for the reader of the bucket" ], - "label": "cluster_get", - "mutates": false, + "label": "get_bucket_readers", + "mutates": true, "payable": false, "returnType": { "displayName": [ - "Result" + "Vec" ], - "type": 49 + "type": 15 }, - "selector": "0xe75411f5" + "selector": "0xb9a7cc1c" }, { "args": [ { - "label": "offset", + "label": "bucket_id", "type": { "displayName": [ - "u32" + "BucketId" ], - "type": 5 + "type": 6 } }, { - "label": "limit", + "label": "reader", "type": { "displayName": [ - "u32" + "AccountId" + ], + "type": 9 + } + } + ], + "docs": [ + " Set permission for the reader of the bucket" + ], + "label": "bucket_set_reader_perm", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0xfc0e94ea" + }, + { + "args": [ + { + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" ], - "type": 5 + "type": 6 } }, { - "label": "filter_manager_id", + "label": "writer", "type": { "displayName": [ - "Option" + "AccountId" ], - "type": 41 + "type": 9 } } ], "docs": [ - " Iterate through all clusters.", - "", - " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", - " The optimal `limit` depends on the size of params.", - "", - " The results can be filtered by manager. Note that paging must still be completed fully." + " Revoke permission for the reader of the bucket" ], - "label": "cluster_list", - "mutates": false, + "label": "bucket_revoke_reader_perm", + "mutates": true, "payable": false, "returnType": { - "displayName": [], - "type": 51 + "displayName": [ + "Result" + ], + "type": 44 }, - "selector": "0xd9db9d44" + "selector": "0xe9bfed5a" }, { "args": [ { - "label": "cdn_node_keys", + "label": "cluster_params", "type": { "displayName": [ - "Vec" + "ClusterParams" ], - "type": 11 + "type": 13 } } ], "docs": [ - " Create a new cluster and return its `cluster_id`.", + " Creates a cluster of Storage nodes and CDN nodes.", + "", + " This endpoint creates a cluster of Storage nodes and CDN nodes with specific parameters.", + " The caller will be the cluster manager (cluster owner). In order to add a Storage or CDN node, the manager must be authorized by the node owner using the `trust_manager` endpoint or be the node owner.", + "", + " # Parameters", + "", + " * `cluster_params` - [Cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format.", + "", + " # Output", + "", + " Returns ID of the created cluster.", "", - " The caller will be its first manager.", + " # Events", "", - " The CDN node ids are provided, which will form a cluster." + " * `ClusterCreated` event on successful cluster creation.", + "", + " # Errors", + "", + " * `InvalidClusterParams` error if there is an invalid cluster parameter. " ], - "label": "cdn_cluster_create", + "label": "cluster_create", "mutates": true, "payable": true, "returnType": { "displayName": [ - "ClusterId" + "Result" ], - "type": 5 + "type": 42 }, - "selector": "0x4344cd7e" + "selector": "0x4c0f21f6" }, { "args": [ @@ -1491,30 +1558,68 @@ "displayName": [ "ClusterId" ], - "type": 5 + "type": 6 } }, { - "label": "usd_per_gb", + "label": "node_key", "type": { "displayName": [ - "Balance" + "NodeKey" + ], + "type": 9 + } + }, + { + "label": "v_nodes", + "type": { + "displayName": [ + "Vec" ], - "type": 8 + "type": 27 } } ], "docs": [ - " Set rate for streaming (price per gb)" + " Adds a Storage node to the targeting cluster.", + "", + " This endpoint adds a physical Storage node along with its virtual nodes to the targeting cluster.", + " Virtual nodes determines a token (position) on the ring in terms of Consistent Hashing.", + " The Storage node can be added to the cluster by cluster manager only.", + "", + " # Parameters", + "", + " * `cluster_id` - ID of the targeting cluster.", + " * `node_key` - Public Key associated with the Storage node.", + " * `v_nodes` - List of tokens (positions) related to the Storage node.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `ClusterNodeAdded` event on successful Storage node addition.", + "", + " # Errors", + "", + " * `ClusterDoesNotExist` error if the cluster does not exist.", + " * `OnlyTrustedClusterManager` error if the caller is not a trusted cluster manager.", + " * `NodeDoesNotExist` error if the adding Storage node does not exist.", + " * `NodeIsAddedToCluster(ClusterId)` error if the adding Storage node is already added to this or another cluster.", + " * `AtLeastOneVNodeHasToBeAssigned(ClusterId, NodeKey)` error if there is a Storage node without any virtual nodes in the cluster.", + " * `VNodesSizeExceedsLimit` error if virtual nodes length exceeds storage capacity." ], - "label": "cdn_set_rate", + "label": "cluster_add_node", "mutates": true, "payable": true, "returnType": { - "displayName": [], - "type": 42 + "displayName": [ + "Result" + ], + "type": 44 }, - "selector": "0x7578922a" + "selector": "0xf7496bdc" }, { "args": [ @@ -1524,23 +1629,55 @@ "displayName": [ "ClusterId" ], - "type": 5 + "type": 6 + } + }, + { + "label": "node_key", + "type": { + "displayName": [ + "NodeKey" + ], + "type": 9 } } ], "docs": [ - " Get rate for streaming (price per gb)" + " Removes a Storage node from the targeting cluster.", + "", + " This endpoint removes a physical Storage node along with its virtual nodes from the targeting cluster.", + " The Storage node can be removed from the cluster either by cluster manager or by the node owner.", + "", + " # Parameters", + "", + " * `cluster_id` - ID of the targeting cluster.", + " * `node_key` - Public Key associated with the Storage node.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `ClusterNodeRemoved` event on successful Storage node removal.", + "", + " # Errors", + "", + " * `ClusterDoesNotExist` error if the cluster does not exist.", + " * `OnlyClusterManagerOrNodeProvider` error if the caller is not the cluster manager or node owner.", + " * `NodeDoesNotExist` error if the removing Storage node does not exist.", + " * `NodeIsNotAddedToCluster(ClusterId)` error if the removing Storage node is not in this cluster." ], - "label": "cdn_get_rate", - "mutates": false, - "payable": true, + "label": "cluster_remove_node", + "mutates": true, + "payable": false, "returnType": { "displayName": [ - "Balance" + "Result" ], - "type": 8 + "type": 44 }, - "selector": "0xa1e3ea8a" + "selector": "0x793e0778" }, { "args": [ @@ -1550,59 +1687,186 @@ "displayName": [ "ClusterId" ], - "type": 5 + "type": 6 } }, { - "label": "aggregates_accounts", + "label": "v_nodes", "type": { "displayName": [ "Vec" ], - "type": 53 + "type": 27 } }, { - "label": "aggregates_nodes", + "label": "new_node_key", "type": { "displayName": [ - "Vec" + "NodeKey" + ], + "type": 9 + } + } + ], + "docs": [ + " Reasignes existing virtual nodes in the targeting cluster.", + "", + " This endpoint reasignes existing virtual nodes to another physical Storage node within the same cluster.", + " All specifying virtual nodes must pre-exist in the cluster and the new physical Storage node must be added to the cluster preliminary.", + "", + " # Parameters", + "", + " * `cluster_id` - ID of the targeting cluster.", + " * `v_nodes` - List of tokens (positions) to reasign for the new physical Storage node.", + " * `new_node_key` - Public Key associated with the Storage node that is being reasigned to the specified virtual nodes.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `ClusterNodeReplaced` event on successful virtual node reassignment.", + "", + " # Errors", + "", + " * `ClusterDoesNotExist` error if the cluster does not exist.", + " * `OnlyClusterManager` error if the caller is not the cluster manager.", + " * `NodeDoesNotExist` error if the new Storage node does not exist.", + " * `NodeIsNotAddedToCluster(ClusterId)` error if the new Storage node is not added to this cluster.", + " * `NodeIsAddedToCluster(ClusterId)` error if the new Storage node is in another cluster.", + " * `VNodeIsNotAssignedToNode(ClusterId, VNodeToken)` error if the there is some virtual node that is being reasigned, but this virtual node is not assigned to any physical node.", + " * `VNodeIsAlreadyAssignedToNode(NodeKey)` - error if there is some virtual node that is already assigned to other physical node within the same cluster.", + " * `AtLeastOneVNodeHasToBeAssigned(ClusterId, NodeKey)` error if there is a Storage node without any virtual nodes in the cluster.", + " * `VNodesSizeExceedsLimit` error if virtual nodes length exceeds storage capacity." + ], + "label": "cluster_replace_node", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x48194ab1" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" ], - "type": 53 + "type": 6 } }, { - "label": "aggregates_buckets", + "label": "cdn_node_key", "type": { "displayName": [ - "Vec" + "CdnNodeKey" + ], + "type": 9 + } + } + ], + "docs": [ + " Adds a CDN node to the targeting cluster.", + "", + " This endpoint adds a CDN node to the targeting cluster.", + " The CDN node can be added to the cluster by cluster manager only.", + "", + " # Parameters", + "", + " * `cluster_id` - ID of the targeting cluster.", + " * `cdn_node_key` - Public Key associated with the CDN node.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `ClusterCdnNodeAdded` event on successful CDN node addition.", + "", + " # Errors", + "", + " * `ClusterDoesNotExist` error if the cluster does not exist.", + " * `OnlyTrustedClusterManager` error if the caller is not a trusted cluster manager.", + " * `CdnNodeDoesNotExist` error if the adding CDN node does not exist.", + " * `CdnNodeIsAddedToCluster(ClusterId)` error if the adding CDN node is already added to this or another cluster." + ], + "label": "cluster_add_cdn_node", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x0b4199f3" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" ], - "type": 55 + "type": 6 } }, { - "label": "era", + "label": "cdn_node_key", "type": { "displayName": [ - "u64" + "CdnNodeKey" ], - "type": 20 + "type": 9 } } ], "docs": [ - " As validator, charge payments from users and allocate undistributed payments to CDN nodes.", + " Removes a CDN node from the targeting cluster.", "", - " As a result CDN cluster revenue increases, which can be distributed between CDN node providers via method cdn_cluster_distribute_revenues." + " This endpoint removes a CDN node the targeting cluster.", + " The CDN node can be removed from the cluster either by cluster manager or by the node owner.", + "", + " # Parameters", + "", + " * `cluster_id` - ID of the targeting cluster.", + " * `cdn_node_key` - Public Key associated with the CDN node.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `ClusterCdnNodeRemoved` event on successful CDN node removal.", + "", + " # Errors", + "", + " * `ClusterDoesNotExist` error if the cluster does not exist.", + " * `OnlyClusterManagerOrCdnNodeProvider` error if the caller is not the cluster manager or node owner.", + " * `CdnNodeDoesNotExist` error if the removing CDN node does not exist.", + " * `CdnNodeIsNotAddedToCluster(ClusterId)` error if the removing CDN node is not in this cluster." ], - "label": "cdn_cluster_put_revenue", + "label": "cluster_remove_cdn_node", "mutates": true, "payable": false, "returnType": { - "displayName": [], - "type": 42 + "displayName": [ + "Result" + ], + "type": 44 }, - "selector": "0x7219be3f" + "selector": "0xff8531d8" }, { "args": [ @@ -1612,22 +1876,53 @@ "displayName": [ "ClusterId" ], - "type": 5 + "type": 6 + } + }, + { + "label": "cluster_params", + "type": { + "displayName": [ + "ClusterParams" + ], + "type": 13 } } ], "docs": [ - " Trigger the distribution of revenues from the cluster to the CDN node providers.", + " Sets parameters for the targeting cluster.", "", - " Anyone can call this method.", + " This enpoint updates [cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. ", + " All cluster parameters must be specified as the endpoint works using SET approach.", "", - " Undistributed payments will be trasnferred, CDN cluster revenue will decrease." + " # Parameters", + "", + " * `cluster_id` - ID of the targeting cluster.", + " * `cluster_params` - [Cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `ClusterParamsSet` event on successful cluster params setting.", + "", + " # Errors", + "", + " * `OnlyClusterManager` error if the caller is not the cluster manager.", + " * `ClusterDoesNotExist` error if the cluster does not exist." ], - "label": "cdn_cluster_distribute_revenues", + "label": "cluster_set_params", "mutates": true, - "payable": false, - "returnType": null, - "selector": "0xfa8d570d" + "payable": true, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x7dac5f9a" }, { "args": [ @@ -1637,80 +1932,120 @@ "displayName": [ "ClusterId" ], - "type": 5 + "type": 6 } } ], "docs": [ - " Get the current status of a cluster." + " Removes a cluster.", + "", + " This enpoint removes the cluster if it does not contain any nodes.", + " Only an empty cluster can be removed.", + "", + " # Parameters", + "", + " * `cluster_id` - ID of the targeting cluster.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `ClusterRemoved` event on successful cluster removal.", + "", + " # Errors", + "", + " * `OnlyClusterManager` error if the caller is not the cluster manager.", + " * `ClusterDoesNotExist` error if the cluster does not exist.", + " * `ClusterIsNotEmpty` error if the removing cluster contains some Storage or CDN nodes." ], - "label": "cdn_cluster_get", - "mutates": false, + "label": "cluster_remove", + "mutates": true, "payable": false, "returnType": { "displayName": [ "Result" ], - "type": 57 + "type": 44 }, - "selector": "0x4b22fbf1" + "selector": "0x2248742a" }, { "args": [ { - "label": "offset", + "label": "cluster_id", "type": { "displayName": [ - "u32" + "ClusterId" ], - "type": 5 + "type": 6 } }, { - "label": "limit", + "label": "node_key", "type": { "displayName": [ - "u32" + "NodeKey" ], - "type": 5 + "type": 9 } }, { - "label": "filter_manager_id", + "label": "status_in_cluster", "type": { "displayName": [ - "Option" + "NodeStatusInCluster" ], - "type": 41 + "type": 23 } } ], "docs": [ - " Iterate through all clusters.", + " Changes Storage node status.", "", - " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", - " The optimal `limit` depends on the size of params.", + " This enpoint changes Storage node status in a cluster.", + "", + " # Parameters", + "", + " * `cluster_id` - ID of the targeting cluster.", + " * `node_key` - Public Key associated with the Storage node.", + " * `status` - Status for the targeting Storage node, can be one of the following: ACTIVE, ADDING, DELETING, OFFLINE.", "", - " The results can be filtered by manager. Note that paging must still be completed fully." + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `ClusterNodeStatusSet` event on successful Storage status change.", + "", + " # Errors", + "", + " * `OnlyClusterManager` error if the caller is not the cluster manager.", + " * `ClusterDoesNotExist` error if the cluster does not exist.", + " * `NodeIsNotAddedToCluster(ClusterId)` error if the Storage node is not in this cluster." ], - "label": "cdn_cluster_list", - "mutates": false, + "label": "cluster_set_node_status", + "mutates": true, "payable": false, "returnType": { - "displayName": [], - "type": 59 + "displayName": [ + "Result" + ], + "type": 44 }, - "selector": "0xb242a64f" + "selector": "0x8078df7f" }, { "args": [ { - "label": "cdn_owner", + "label": "cluster_id", "type": { "displayName": [ - "AccountId" + "ClusterId" ], - "type": 2 + "type": 6 } }, { @@ -1719,517 +2054,721 @@ "displayName": [ "CdnNodeKey" ], - "type": 2 + "type": 9 } }, { - "label": "commit", + "label": "status_in_cluster", "type": { "displayName": [ - "Commit" + "NodeStatusInCluster" ], - "type": 35 + "type": 23 } } ], "docs": [ - " CDN node operator sets the commit for current era." + " Changes CDN node status.", + "", + " This enpoint changes CDN node status in a cluster.", + "", + " # Parameters", + "", + " * `cluster_id` - ID of the targeting cluster.", + " * `cdn_node_key` - Public Key associated with the CDN node.", + " * `status` - Status for the targeting CDN node, can be one of the following: ACTIVE, ADDING, DELETING, OFFLINE.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `ClusterCdnNodeStatusSet` event on successful CDN status change.", + "", + " # Errors", + "", + " * `OnlyClusterManager` error if the caller is not the cluster manager.", + " * `ClusterDoesNotExist` error if the cluster does not exist.", + " * `CdnNodeIsNotAddedToCluster(ClusterId)` error if the CDN node is not in this cluster." ], - "label": "set_commit", + "label": "cluster_set_cdn_node_status", "mutates": true, "payable": false, - "returnType": null, - "selector": "0xe445e1fd" + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x577027ba" }, { "args": [ { - "label": "cdn_owner", + "label": "cluster_id", "type": { "displayName": [ - "AccountId" + "ClusterId" ], - "type": 2 + "type": 6 } } ], "docs": [ - " Return the last commit submitted by CDN node operator" + " Gets a cluster.", + "", + " This enpoint gets the targeting cluster along with its parameters, Storage and CDN nodes.", + "", + " # Parameters", + "", + " * `cluster_id` - ID of the targeting cluster.", + "", + " # Output", + "", + " Returns `ClusterInfo` data transfer object.", + "", + " # Errors", + "", + " * `ClusterDoesNotExist` error if the cluster does not exist." ], - "label": "get_commit", + "label": "cluster_get", "mutates": false, "payable": false, "returnType": { "displayName": [ - "Vec" + "Result" ], - "type": 33 + "type": 52 }, - "selector": "0x5329f551" + "selector": "0xe75411f5" }, { "args": [ { - "label": "cdn_node_key", + "label": "offset", "type": { "displayName": [ - "CdnNodeKey" + "u32" + ], + "type": 6 + } + }, + { + "label": "limit", + "type": { + "displayName": [ + "u32" + ], + "type": 6 + } + }, + { + "label": "filter_manager_id", + "type": { + "displayName": [ + "Option" ], - "type": 2 + "type": 41 } } ], "docs": [ - " Return last era validated per CDN node" + " Gets a paginated list of clusters.", + "", + " This enpoint gets a paginated list of clusters along with their parameters, Storage and CDN nodes.", + " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", + " The optimal `limit` depends on the size of params.", + "", + " # Parameters", + "", + " * `offset` - starting offset.", + " * `limit` - page limit.", + " * `filter_manager_id` - optional filter by cluster manager.", + "", + " # Errors", + "", + " No errors. In case a pagination param is out of bounds, an empty list will be returned." ], - "label": "get_validated_commit", + "label": "cluster_list", "mutates": false, "payable": false, "returnType": { - "displayName": [ - "EraAndTimestamp" - ], - "type": 38 + "displayName": [], + "type": 54 }, - "selector": "0x7d497bc1" + "selector": "0xd9db9d44" }, { "args": [ { - "label": "era_config", + "label": "cluster_id", "type": { "displayName": [ - "EraConfig" + "ClusterId" ], - "type": 61 + "type": 6 + } + }, + { + "label": "amount", + "type": { + "displayName": [ + "Resource" + ], + "type": 6 } } ], "docs": [ - " Set the new configs for era" + " As manager, reserve more resources for the cluster from the free capacity of nodes.", + "", + " The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes)." ], - "label": "set_era", + "label": "cluster_reserve_resource", "mutates": true, "payable": false, - "returnType": { - "displayName": [], - "type": 42 - }, - "selector": "0x49a5b8f7" - }, - { - "args": [], - "docs": [ - " Return current status of an era" - ], - "label": "get_era", - "mutates": false, - "payable": false, "returnType": { "displayName": [ - "EraStatus" + "Result" ], - "type": 62 + "type": 44 }, - "selector": "0x617f696b" + "selector": "0xb5e38125" }, { - "args": [], + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 6 + } + } + ], "docs": [ - " Return current era settings" + " Trigger the distribution of revenues from the cluster to the providers." ], - "label": "get_era_settings", - "mutates": false, + "label": "cluster_distribute_revenues", + "mutates": true, "payable": false, "returnType": { "displayName": [ - "EraConfig" + "Result" ], - "type": 61 + "type": 44 }, - "selector": "0x84b61468" + "selector": "0xe71e66fc" }, { "args": [ { - "label": "manager", + "label": "cluster_id", "type": { "displayName": [ - "AccountId" + "ClusterId" + ], + "type": 6 + } + }, + { + "label": "usd_per_gb", + "type": { + "displayName": [ + "Balance" ], - "type": 2 + "type": 12 } } ], "docs": [ - " As node provider, authorize a cluster manager to use his nodes." + " Set rate for streaming (price per gb)" ], - "label": "cdn_node_trust_manager", + "label": "cdn_set_rate", "mutates": true, "payable": true, - "returnType": null, - "selector": "0x372daa96" + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x7578922a" }, { "args": [ { - "label": "manager", + "label": "cluster_id", "type": { "displayName": [ - "AccountId" + "ClusterId" ], - "type": 2 + "type": 6 } } ], "docs": [ - " As node provider, revoke the authorization of a cluster manager to use his nodes." + " Get rate for streaming (price per gb)" ], - "label": "cdn_node_distrust_manager", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0xf67f5438" + "label": "cdn_get_rate", + "mutates": false, + "payable": true, + "returnType": { + "displayName": [ + "Result" + ], + "type": 56 + }, + "selector": "0xa1e3ea8a" }, { "args": [ { - "label": "cdn_node_key", + "label": "cluster_id", "type": { "displayName": [ - "CdnNodeKey" + "ClusterId" ], - "type": 2 + "type": 6 } }, { - "label": "cdn_node_params", + "label": "aggregates_accounts", "type": { "displayName": [ - "CdnNodeParams" + "Vec" ], - "type": 14 + "type": 57 } - } - ], - "docs": [ - " Create a new node and return its `node_id`.", - "", - " The caller will be its owner.", - "", - " `node_params` is configuration used by clients and nodes. In particular, this contains the URL to the service. See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "cdn_node_create", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [ - "CdnNodeKey" - ], - "type": 2 - }, - "selector": "0xe8aa4ade" - }, - { - "args": [ + }, { - "label": "cdn_node_key", + "label": "aggregates_nodes", "type": { "displayName": [ - "CdnNodeKey" + "Vec" ], - "type": 2 + "type": 57 } }, { - "label": "cdn_node_params", + "label": "aggregates_buckets", "type": { "displayName": [ - "CdnNodeParams" + "Vec" + ], + "type": 59 + } + }, + { + "label": "era", + "type": { + "displayName": [ + "u64" ], - "type": 14 + "type": 28 } } ], "docs": [ - " Change the `node_params`, which is configuration used by clients and nodes.", + " As validator, charge payments from users and allocate undistributed payments to CDN nodes.", "", - " See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" + " As a result CDN cluster revenue increases, which can be distributed between CDN node providers via method cdn_cluster_distribute_revenues." ], - "label": "cdn_node_change_params", + "label": "cluster_put_cdn_revenue", "mutates": true, - "payable": true, - "returnType": null, - "selector": "0xf52c20f5" + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0xeb8ec51c" }, { "args": [ { - "label": "cdn_node_key", + "label": "cluster_id", "type": { "displayName": [ - "CdnNodeKey" + "ClusterId" ], - "type": 2 + "type": 6 } } ], "docs": [ - " Get the current state of the cdn node" + " Trigger the distribution of revenues from the cluster to the CDN node providers.", + "", + " Anyone can call this method.", + "", + " Undistributed payments will be trasnferred, CDN cluster revenue will decrease." ], - "label": "cdn_node_get", - "mutates": false, + "label": "cluster_distribute_cdn_revenue", + "mutates": true, "payable": false, "returnType": { "displayName": [ "Result" ], - "type": 64 + "type": 44 }, - "selector": "0xf9a5a813" + "selector": "0x804ac6e0" }, { "args": [ { - "label": "offset", + "label": "cdn_owner", "type": { "displayName": [ - "u32" + "AccountId" ], - "type": 5 + "type": 9 } }, { - "label": "limit", + "label": "cdn_node_key", "type": { "displayName": [ - "u32" + "CdnNodeKey" ], - "type": 5 + "type": 9 } }, { - "label": "filter_provider_id", + "label": "commit", "type": { "displayName": [ - "Option" + "Commit" ], - "type": 41 + "type": 37 } } ], "docs": [ - " Iterate through all nodes.", - "", - " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", - " The optimal `limit` depends on the size of params.", - "", - " The results can be filtered by owner. Note that paging must still be completed fully." + " CDN node operator sets the commit for current era." ], - "label": "cdn_node_list", - "mutates": false, + "label": "set_commit", + "mutates": true, "payable": false, "returnType": { - "displayName": [], - "type": 66 + "displayName": [ + "Result" + ], + "type": 44 }, - "selector": "0xf8589aae" + "selector": "0xe445e1fd" }, { "args": [ { - "label": "node_key", + "label": "cdn_owner", "type": { "displayName": [ - "CdnNodeKey" + "AccountId" ], - "type": 2 + "type": 9 } } ], "docs": [ - " Remove cdn node by id ", - " ", - " Only the provider of the node can remove the node (not related to the public key)", - " ", - " The underlying algorithm swaps the moved to be removed with the last one added, hence the id of the last one added will be updated" + " Return the last commit submitted by CDN node operator" ], - "label": "cdn_node_remove", - "mutates": true, + "label": "get_commit", + "mutates": false, "payable": false, "returnType": { "displayName": [ - "Result" + "Vec" ], - "type": 68 + "type": 35 }, - "selector": "0xe068fb34" + "selector": "0x5329f551" }, { "args": [ { - "label": "manager", + "label": "cdn_node_key", "type": { "displayName": [ - "AccountId" + "CdnNodeKey" ], - "type": 2 + "type": 9 } } ], "docs": [ - " As node provider, authorize a cluster manager to use his nodes." + " Return last era validated per CDN node" ], - "label": "node_trust_manager", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x6fd54a01" + "label": "get_validated_commit", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "EraAndTimestamp" + ], + "type": 40 + }, + "selector": "0x7d497bc1" }, { "args": [ { - "label": "manager", + "label": "era_config", "type": { "displayName": [ - "AccountId" + "EraConfig" ], - "type": 2 + "type": 61 } } ], "docs": [ - " As node provider, revoke the authorization of a cluster manager to use his nodes." + " Set the new configs for era" ], - "label": "node_distrust_manager", + "label": "set_era", "mutates": true, "payable": false, - "returnType": null, - "selector": "0x40912279" + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x49a5b8f7" + }, + { + "args": [], + "docs": [ + " Return current status of an era" + ], + "label": "get_era", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "EraStatus" + ], + "type": 62 + }, + "selector": "0x617f696b" + }, + { + "args": [], + "docs": [ + " Return current era settings" + ], + "label": "get_era_settings", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "EraConfig" + ], + "type": 61 + }, + "selector": "0x84b61468" }, { "args": [ { - "label": "node_key", + "label": "cdn_node_key", "type": { "displayName": [ - "NodeKey" + "CdnNodeKey" ], - "type": 2 + "type": 9 } }, { - "label": "rent_per_month", + "label": "cdn_node_params", "type": { "displayName": [ - "Balance" + "CdnNodeParams" ], - "type": 8 + "type": 13 } - }, - { - "label": "node_params", - "type": { - "displayName": [ - "NodeParams" - ], - "type": 14 - } - }, - { - "label": "capacity", - "type": { - "displayName": [ - "Resource" - ], - "type": 5 - } - }, + } + ], + "docs": [ + " Creates a CDN node", + "", + " This endpoint creates a CDN node with specific parameters.", + " The caller will be the node owner (node provider).", + "", + " # Parameters", + "", + " * `cdn_node_key` - Public Keys of the CDN node that should be treated as node identifier.", + " * `cdn_node_params` - [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format.", + "", + " # Output", + "", + " Returns Public Key of the created CDN node.", + "", + " # Events", + "", + " * `CdnNodeCreated` event on successful CDN node creation.", + "", + " # Errors", + "", + " * `CdnNodeAlreadyExists` error if a CDN node with the same Public Key is already created.", + " * `InvalidParams(message)` error if there is some invalid configuration parameter." + ], + "label": "cdn_node_create", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [ + "Result" + ], + "type": 64 + }, + "selector": "0xe8aa4ade" + }, + { + "args": [ { - "label": "status", + "label": "cdn_node_key", "type": { "displayName": [ - "NodeStatusInCluster" + "CdnNodeKey" ], - "type": 27 + "type": 9 } } ], "docs": [ - " Create a new node and return its `node_id`.", + " Removes a CDN node.", + "", + " This enpoint removes the targeting CDN Node if it is not added to some cluster.", + " Only a node that is not a member of some cluster can be removed.", + "", + " # Parameters", + "", + " * `cdn_node_key` - Public Key associated with the CDN node.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `CdnNodeRemoved` event on successful CDN node removal.", "", - " The caller will be its owner.", + " # Errors", "", - " `node_params` is configuration used by clients and nodes. In particular, this contains the URL to the service. See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" + " * `OnlyCdnNodeProvider` error if the caller is not the CDN node owner.", + " * `CdnNodeDoesNotExist` error if the CDN node does not exist.", + " * `CdnNodeIsAddedToCluster(ClusterId)` error if the removing CDN node is added to some cluster." ], - "label": "node_create", + "label": "cdn_node_remove", "mutates": true, - "payable": true, + "payable": false, "returnType": { "displayName": [ - "NodeKey" + "Result" ], - "type": 2 + "type": 44 }, - "selector": "0xb77ac1bb" + "selector": "0xe068fb34" }, { "args": [ { - "label": "node_key", + "label": "cdn_node_key", "type": { "displayName": [ - "NodeKey" + "CdnNodeKey" ], - "type": 2 + "type": 9 } }, { - "label": "node_params", + "label": "cdn_node_params", "type": { "displayName": [ - "NodeParams" + "CdnNodeParams" ], - "type": 14 + "type": 13 } } ], "docs": [ - " Change the `node_params`, which is configuration used by clients and nodes.", + " Sets parameters for the targeting CDN node.", + "", + " This enpoint updates [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. ", + " All CDN node parameters must be specified as the endpoint works using SET approach.", + "", + " # Parameters", + "", + " * `cdn_node_key` - Public Key associated with the CDN node.", + " * `cdn_node_params` - [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `CdnNodeParamsSet` event on successful CDN node params setting.", + "", + " # Errors", "", - " See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" + " * `OnlyCdnNodeProvider` error if the caller is not the CDN node owner.", + " * `CdnNodeDoesNotExist` error if the CDN node does not exist." ], - "label": "node_change_params", + "label": "cdn_node_set_params", "mutates": true, "payable": true, - "returnType": null, - "selector": "0x258ccb2a" + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0xdf8b696e" }, { "args": [ { - "label": "node_key", + "label": "cdn_node_key", "type": { "displayName": [ - "NodeKey" + "CdnNodeKey" ], - "type": 2 + "type": 9 } } ], "docs": [ - " Get the current status of a node." + " Gets a CDN node.", + "", + " This enpoint gets the targeting CDN node along with its parameters.", + "", + " # Parameters", + "", + " * `cdn_node_key` - Public Key associated with the CDN node.", + "", + " # Output", + "", + " Returns `CdnNodeInfo` data transfer object.", + "", + " # Errors", + "", + " * `CdnNodeDoesNotExist` error if the CDN node does not exist." ], - "label": "node_get", + "label": "cdn_node_get", "mutates": false, "payable": false, "returnType": { "displayName": [ "Result" ], - "type": 69 + "type": 65 }, - "selector": "0x847f3997" + "selector": "0xf9a5a813" }, { "args": [ @@ -2239,7 +2778,7 @@ "displayName": [ "u32" ], - "type": 5 + "type": 6 } }, { @@ -2248,7 +2787,7 @@ "displayName": [ "u32" ], - "type": 5 + "type": 6 } }, { @@ -2262,21 +2801,30 @@ } ], "docs": [ - " Iterate through all nodes.", + " Gets a paginated list of CDN nodes.", "", + " This enpoint gets a paginated list of CDN nodes along with their parameters.", " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", " The optimal `limit` depends on the size of params.", "", - " The results can be filtered by owner. Note that paging must still be completed fully." + " # Parameters", + "", + " * `offset` - starting offset.", + " * `limit` - page limit.", + " * `filter_provider_id` - optional filter by CDN node owner.", + "", + " # Errors", + "", + " No errors. In case a pagination param is out of bounds, an empty list will be returned." ], - "label": "node_list", + "label": "cdn_node_list", "mutates": false, "payable": false, "returnType": { "displayName": [], - "type": 71 + "type": 67 }, - "selector": "0x423286d6" + "selector": "0xf8589aae" }, { "args": [ @@ -2286,156 +2834,357 @@ "displayName": [ "NodeKey" ], - "type": 2 + "type": 9 + } + }, + { + "label": "node_params", + "type": { + "displayName": [ + "NodeParams" + ], + "type": 13 + } + }, + { + "label": "capacity", + "type": { + "displayName": [ + "Resource" + ], + "type": 6 + } + }, + { + "label": "rent_per_month", + "type": { + "displayName": [ + "Balance" + ], + "type": 12 } } ], "docs": [ - " Remove node by id ", - " ", - " Only the provider of the node can remove the node (not related to the public key)", - " ", - " The underlying algorithm swaps the moved to be removed with the last one added, hence the id of the last one added will be updated" + " Creates a Storage node", + "", + " This endpoint creates a Storage node with specific parameters.", + " The caller will be the node owner (node provider).", + "", + " # Parameters", + "", + " * `node_key` - Public Keys of the Storage node that should be treated as node identifier.", + " * `node_params` - [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format.", + " * `capacity` - Measure used to evaluate physical node hardware resources.", + " * `rent_per_month` - Renting per month.", + "", + " # Output", + "", + " Returns Public Key of the created Storage node.", + "", + " # Events", + "", + " * `NodeCreated` event on successful Storage node creation.", + "", + " # Errors", + "", + " * `NodeAlreadyExists` error if a Storage node with the same Public Key is already created.", + " * `InvalidParams(message)` error if there is some invalid configuration parameter." ], - "label": "node_remove", + "label": "node_create", "mutates": true, - "payable": false, + "payable": true, "returnType": { "displayName": [ "Result" ], - "type": 68 - }, - "selector": "0x42e5f273" - }, - { - "args": [], - "docs": [ - " Get the Fee Percentage Basis Points that will be charged by the protocol" - ], - "label": "get_fee_bp", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "u32" - ], - "type": 5 + "type": 64 }, - "selector": "0x0d5daf5f" + "selector": "0xb77ac1bb" }, { "args": [ { - "label": "fee_bp", + "label": "node_key", "type": { "displayName": [ - "u32" + "NodeKey" ], - "type": 5 + "type": 9 } } ], "docs": [ - " Return the last commit submitted by CDN node operator" + " Removes a Storage node.", + "", + " This enpoint removes the targeting Storage Node if it is not added to some cluster.", + " Only a node that is not a member of some cluster can be removed.", + "", + " # Parameters", + "", + " * `node_key` - Public Key associated with the Storage node.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `NodeRemoved` event on successful Storage node removal.", + "", + " # Errors", + "", + " * `OnlyNodeProvider` error if the caller is not the Storage node owner.", + " * `NodeDoesNotExist` error if the Storage node does not exist.", + " * `NodeIsAddedToCluster(ClusterId)` error if the removing Storage node is added to some cluster." ], - "label": "set_fee_bp", + "label": "node_remove", "mutates": true, "payable": false, - "returnType": { - "displayName": [], - "type": 42 - }, - "selector": "0xc5e3e2ca" - }, - { - "args": [], - "docs": [ - " Return fees accumulated by the protocol" - ], - "label": "get_protocol_revenues", - "mutates": false, - "payable": false, "returnType": { "displayName": [ - "Cash" + "Result" ], - "type": 17 + "type": 44 }, - "selector": "0x07c63885" + "selector": "0x42e5f273" }, { "args": [ { - "label": "amount", + "label": "node_key", "type": { "displayName": [ - "u128" + "NodeKey" ], - "type": 8 + "type": 9 } - } - ], - "docs": [ - " Pay the revenues accumulated by the protocol" - ], - "label": "protocol_withdraw_revenues", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 42 - }, - "selector": "0x85c6fa6d" - }, - { - "args": [], - "docs": [ - " As user, deposit tokens on the account of the caller from the transaction value. This deposit", - " can be used to pay for the services to buckets of the account." - ], - "label": "account_deposit", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [], - "type": 42 - }, - "selector": "0xc311af62" - }, - { - "args": [ + }, { - "label": "bond_amount", + "label": "node_params", "type": { "displayName": [ - "Balance" + "NodeParams" ], - "type": 8 + "type": 13 } } ], "docs": [ - " As user, bond some amount of tokens from the withdrawable balance. These funds will be used to pay for CDN node service." + " Sets parameters for the targeting Storage node.", + "", + " This enpoint updates [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. ", + " All Storage node parameters must be specified as the endpoint works using SET approach.", + "", + " # Parameters", + "", + " * `node_key` - Public Key associated with the Storage node.", + " * `node_params` - [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. ", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `NodeParamsSet` event on successful Storage node params setting.", + "", + " # Errors", + "", + " * `OnlyNodeProvider` error if the caller is not the Storage node owner.", + " * `NodeDoesNotExist` error if the Storage node does not exist." ], - "label": "account_bond", + "label": "node_set_params", "mutates": true, "payable": true, "returnType": { - "displayName": [], - "type": 42 + "displayName": [ + "Result" + ], + "type": 44 }, - "selector": "0xe9fad0bf" + "selector": "0xfb74fd2e" }, { "args": [ { - "label": "amount_to_unbond", + "label": "node_key", "type": { "displayName": [ - "Cash" + "NodeKey" ], - "type": 17 + "type": 9 + } + } + ], + "docs": [ + " Gets a Storage node.", + "", + " This enpoint gets the targeting Storage node along with its parameters.", + "", + " # Parameters", + "", + " * `node_key` - Public Key associated with the Storage node.", + "", + " # Output", + "", + " Returns `NodeInfo` data transfer object.", + "", + " # Errors", + "", + " * `NodeDoesNotExist` error if the Storage node does not exist." + ], + "label": "node_get", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 69 + }, + "selector": "0x847f3997" + }, + { + "args": [ + { + "label": "offset", + "type": { + "displayName": [ + "u32" + ], + "type": 6 + } + }, + { + "label": "limit", + "type": { + "displayName": [ + "u32" + ], + "type": 6 + } + }, + { + "label": "filter_provider_id", + "type": { + "displayName": [ + "Option" + ], + "type": 41 + } + } + ], + "docs": [ + " Gets a paginated list of Storage nodes.", + "", + " This enpoint gets a paginated list of Storage nodes along with their parameters.", + " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", + " The optimal `limit` depends on the size of params.", + "", + " # Parameters", + "", + " * `offset` - starting offset.", + " * `limit` - page limit.", + " * `filter_provider_id` - optional filter by Storage node owner.", + "", + " # Errors", + "", + " No errors. In case a pagination param is out of bounds, an empty list will be returned." + ], + "label": "node_list", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [], + "type": 71 + }, + "selector": "0x423286d6" + }, + { + "args": [], + "docs": [ + " Get the Fee Percentage Basis Points that will be charged by the protocol" + ], + "label": "get_protocol_fee_bp", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "u128" + ], + "type": 12 + }, + "selector": "0x650857a8" + }, + { + "args": [], + "docs": [ + " Return fees accumulated by the protocol" + ], + "label": "get_protocol_revenues", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Cash" + ], + "type": 18 + }, + "selector": "0x07c63885" + }, + { + "args": [], + "docs": [ + " As user, deposit tokens on the account of the caller from the transaction value. This deposit", + " can be used to pay for the services to buckets of the account." + ], + "label": "account_deposit", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0xc311af62" + }, + { + "args": [ + { + "label": "bond_amount", + "type": { + "displayName": [ + "Balance" + ], + "type": 12 + } + } + ], + "docs": [ + " As user, bond some amount of tokens from the withdrawable balance. These funds will be used to pay for CDN node service." + ], + "label": "account_bond", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0xe9fad0bf" + }, + { + "args": [ + { + "label": "amount_to_unbond", + "type": { + "displayName": [ + "Cash" + ], + "type": 18 } } ], @@ -2446,8 +3195,10 @@ "mutates": true, "payable": true, "returnType": { - "displayName": [], - "type": 42 + "displayName": [ + "Result" + ], + "type": 44 }, "selector": "0xf7ea2c67" }, @@ -2462,8 +3213,10 @@ "mutates": true, "payable": true, "returnType": { - "displayName": [], - "type": 42 + "displayName": [ + "Result" + ], + "type": 44 }, "selector": "0x98173716" }, @@ -2475,7 +3228,7 @@ "displayName": [ "AccountId" ], - "type": 2 + "type": 9 } } ], @@ -2505,7 +3258,7 @@ "displayName": [ "Balance" ], - "type": 8 + "type": 12 }, "selector": "0xe4a4652a" }, @@ -2517,7 +3270,7 @@ "displayName": [ "Balance" ], - "type": 8 + "type": 12 } } ], @@ -2529,18 +3282,23 @@ "label": "account_set_usd_per_cere", "mutates": true, "payable": false, - "returnType": null, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, "selector": "0x48d45ee8" }, { "args": [ { - "label": "grantee", + "label": "account_id", "type": { "displayName": [ "AccountId" ], - "type": 2 + "type": 9 } }, { @@ -2554,8 +3312,23 @@ } ], "docs": [ - " Check whether the given account has the given permission currently,", - " or the SuperAdmin permission." + " Checks for permission existence.", + "", + " This enpoint checks whether the given account has the given permission.", + " Super-admin will always have all permissions.", + "", + " # Parameters", + "", + " * `account_id` - account to check permissions.", + " * `permission` - permission to check.", + "", + " # Output", + "", + " Returns true if the account has permissions, false otherwise.", + "", + " # Errors", + "", + " No errors." ], "label": "has_permission", "mutates": false, @@ -2564,39 +3337,101 @@ "displayName": [ "bool" ], - "type": 9 + "type": 3 }, "selector": "0xe0942492" }, { "args": [ { - "label": "grantee", + "label": "manager", "type": { "displayName": [ "AccountId" ], - "type": 2 + "type": 9 } - }, + } + ], + "docs": [ + " Grants permissions for a cluster manager.", + "", + " This endpoint grants permissions for a cluster manager ro manage Storage or CDN node owner.", + " After the permission is granted, the cluster manager can add nodes to the cluster.", + " Permissions can be granted by Storage or CDN node owner.", + "", + " # Parameters", + "", + " * `manager` - cluster manager account.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `PermissionGranted` event on successful manager permissions granting", + "", + " # Errors", + "", + " No errors. The endpoint is idempotent." + ], + "label": "grant_trusted_manager_permission", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0xea0cbdcd" + }, + { + "args": [ { - "label": "permission", + "label": "manager", "type": { "displayName": [ - "Permission" + "AccountId" ], - "type": 74 + "type": 9 } } ], "docs": [ - " As SuperAdmin, grant any permission to any account." + " Revokes permissions from cluster manager.", + "", + " This endpoint revokes permissions from a cluster manager to manage Storage or CDN node owner.", + " After the permission is revoked, the cluster manager can add nodes to the cluster.", + " Permissions can be revoked by Storage or CDN node owner.", + "", + " # Parameters", + "", + " * `manager` - cluster manager account.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `PermissionRevoked` event on successful manager permissions revoking", + "", + " # Errors", + "", + " No errors. The endpoint is idempotent." ], - "label": "admin_grant_permission", + "label": "revoke_trusted_manager_permission", "mutates": true, - "payable": true, - "returnType": null, - "selector": "0xbe41ea55" + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x83532355" }, { "args": [ @@ -2606,7 +3441,7 @@ "displayName": [ "AccountId" ], - "type": 2 + "type": 9 } }, { @@ -2620,23 +3455,215 @@ } ], "docs": [ - " As SuperAdmin, revoke any permission to any account." + " Grants any permission.", + "", + " This endpoint grants any permissions for any account by the Super-admin.", + "", + " # Parameters", + "", + " * `grantee` - account to grant permission.", + " * `permission` - permission type.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `PermissionGranted` event on successful permissions granting", + "", + " # Errors", + "", + " Returns `OnlySuperAdmin` error if the caller is not the Super-admin." ], - "label": "admin_revoke_permission", + "label": "admin_grant_permission", "mutates": true, "payable": false, - "returnType": null, - "selector": "0x6b150666" + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0xbe41ea55" }, { "args": [ { - "label": "amount", + "label": "grantee", "type": { "displayName": [ - "Balance" + "AccountId" + ], + "type": 9 + } + }, + { + "label": "permission", + "type": { + "displayName": [ + "Permission" ], - "type": 8 + "type": 74 + } + } + ], + "docs": [ + " Revokes any permission.", + "", + " This endpoint revokes any permissions from any account by the Super-admin.", + "", + " # Parameters", + "", + " * `grantee` - account to revoke permission.", + " * `permission` - permission type.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `PermissionRevoked` event on successful permissions revoking", + "", + " # Errors", + "", + " Returns `OnlySuperAdmin` error if the caller is not the Super-admin." + ], + "label": "admin_revoke_permission", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x6b150666" + }, + { + "args": [ + { + "label": "node_key", + "type": { + "displayName": [ + "NodeKey" + ], + "type": 9 + } + }, + { + "label": "new_owner", + "type": { + "displayName": [ + "AccountId" + ], + "type": 9 + } + } + ], + "docs": [ + " Transfers Storage node ownership.", + "", + " This endpoint transfers Storage node ownership from Super-admin account to the targeting account forever.", + " This action is usually required only once after the Storage node certification process.", + "", + " # Parameters", + "", + " * `node_key` - Public Key associated with the Storage node.", + " * `new_owner` - New Storage node owner", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `NodeOwnershipTransferred` event on successful Storage node ownership transfer", + "", + " # Errors", + "", + " * `OnlySuperAdmin` error if the caller is not the Super-admin.", + " * `NodeDoesNotExist` error if the Storage node does not exist.", + " * `NodeProviderIsNotSuperAdmin` error if the owner of the targeting node is not the Super-admin." + ], + "label": "admin_transfer_node_ownership", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x783b382d" + }, + { + "args": [ + { + "label": "cdn_node_key", + "type": { + "displayName": [ + "CdnNodeKey" + ], + "type": 9 + } + }, + { + "label": "new_owner", + "type": { + "displayName": [ + "AccountId" + ], + "type": 9 + } + } + ], + "docs": [ + " Transfers CDN node ownership.", + "", + " This endpoint transfers CDN node ownership from Super-admin account to the targeting account forever.", + " This action is usually required only once after the CDN node certification process.", + "", + " # Parameters", + "", + " * `cdn_node_key` - Public Key associated with the CDN node.", + " * `new_owner` - CDN node owner", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `CdnNodeOwnershipTransferred` event on successful CDN node ownership transfer", + "", + " # Errors", + "", + " * `OnlySuperAdmin` error if the caller is not the Super-admin.", + " * `CdnNodeDoesNotExist` error if the Storage node does not exist.", + " * `CdnNodeOwnerIsNotSuperAdmin` error if the owner of the targeting node is not the Super-admin." + ], + "label": "admin_transfer_cdn_node_ownership", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0xcd9821be" + }, + { + "args": [ + { + "label": "amount", + "type": { + "displayName": [ + "Balance" + ], + "type": 12 } } ], @@ -2648,7 +3675,12 @@ "label": "admin_withdraw", "mutates": true, "payable": false, - "returnType": null, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, "selector": "0x2f6e0868" }, { @@ -2657,7 +3689,7 @@ "label": "config", "type": { "displayName": [ - "FeeConfig" + "NetworkFeeConfig" ], "type": 75 } @@ -2666,11 +3698,66 @@ "docs": [ " As SuperAdmin, set the network and cluster fee configuration." ], - "label": "admin_set_fee_config", + "label": "admin_set_network_fee_config", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x14649395" + }, + { + "args": [ + { + "label": "amount", + "type": { + "displayName": [ + "u128" + ], + "type": 12 + } + } + ], + "docs": [ + " Pay the revenues accumulated by the protocol" + ], + "label": "admin_withdraw_protocol_revenues", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0xa781da48" + }, + { + "args": [ + { + "label": "protocol_fee_bp", + "type": { + "displayName": [ + "u128" + ], + "type": 12 + } + } + ], + "docs": [], + "label": "admin_set_protocol_fee_bp", "mutates": true, "payable": false, - "returnType": null, - "selector": "0x00d441e7" + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0x00e00535" }, { "args": [], @@ -2684,9 +3771,90 @@ "displayName": [ "Vec" ], - "type": 11 + "type": 15 }, "selector": "0xef03ead7" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 6 + } + } + ], + "docs": [], + "label": "get_v_nodes_by_cluster", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Vec" + ], + "type": 27 + }, + "selector": "0x94eb8da6" + }, + { + "args": [ + { + "label": "node_key", + "type": { + "displayName": [ + "NodeKey" + ], + "type": 9 + } + } + ], + "docs": [], + "label": "get_v_nodes_by_node", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Vec" + ], + "type": 27 + }, + "selector": "0xf0dfbd13" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 6 + } + }, + { + "label": "v_node", + "type": { + "displayName": [ + "VNodeToken" + ], + "type": 28 + } + } + ], + "docs": [], + "label": "get_node_by_v_node", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 64 + }, + "selector": "0xea47048e" } ] }, @@ -2704,12 +3872,12 @@ "ty": 0 } }, - "name": null + "name": "perms" } ] } }, - "name": "buckets" + "name": "perms" }, { "layout": { @@ -2719,60 +3887,42 @@ "layout": { "cell": { "key": "0x0100000000000000000000000000000000000000000000000000000000000000", - "ty": 10 + "ty": 6 } }, - "name": "writers" + "name": "next_bucket_id" }, { "layout": { "cell": { "key": "0x0200000000000000000000000000000000000000000000000000000000000000", - "ty": 10 + "ty": 7 } }, - "name": "readers" - } - ] - } - }, - "name": "buckets_perms" - }, - { - "layout": { - "struct": { - "fields": [ + "name": "buckets" + }, { "layout": { "cell": { "key": "0x0300000000000000000000000000000000000000000000000000000000000000", - "ty": 13 + "ty": 14 } }, - "name": null - } - ] - } - }, - "name": "bucket_params" - }, - { - "layout": { - "struct": { - "fields": [ + "name": "writers" + }, { "layout": { "cell": { "key": "0x0400000000000000000000000000000000000000000000000000000000000000", - "ty": 15 + "ty": 14 } }, - "name": null + "name": "readers" } ] } }, - "name": "clusters" + "name": "buckets" }, { "layout": { @@ -2782,33 +3932,24 @@ "layout": { "cell": { "key": "0x0500000000000000000000000000000000000000000000000000000000000000", - "ty": 21 + "ty": 6 } }, - "name": null - } - ] - } - }, - "name": "cdn_clusters" - }, - { - "layout": { - "struct": { - "fields": [ + "name": "next_cluster_id" + }, { "layout": { "cell": { "key": "0x0600000000000000000000000000000000000000000000000000000000000000", - "ty": 13 + "ty": 16 } }, - "name": null + "name": "clusters" } ] } }, - "name": "cluster_params" + "name": "clusters" }, { "layout": { @@ -2818,7 +3959,7 @@ "layout": { "cell": { "key": "0x0700000000000000000000000000000000000000000000000000000000000000", - "ty": 23 + "ty": 19 } }, "name": "cdn_nodes" @@ -2827,7 +3968,7 @@ "layout": { "cell": { "key": "0x0800000000000000000000000000000000000000000000000000000000000000", - "ty": 11 + "ty": 15 } }, "name": "keys" @@ -2845,7 +3986,7 @@ "layout": { "cell": { "key": "0x0900000000000000000000000000000000000000000000000000000000000000", - "ty": 25 + "ty": 24 } }, "name": "nodes" @@ -2854,7 +3995,7 @@ "layout": { "cell": { "key": "0x0a00000000000000000000000000000000000000000000000000000000000000", - "ty": 11 + "ty": 15 } }, "name": "keys" @@ -2872,42 +4013,33 @@ "layout": { "cell": { "key": "0x0b00000000000000000000000000000000000000000000000000000000000000", - "ty": 28 + "ty": 26 } }, - "name": null + "name": "v_nodes_map" }, { "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0c00000000000000000000000000000000000000000000000000000000000000", - "ty": 8 - } - }, - "name": null - } - ] + "cell": { + "key": "0x0c00000000000000000000000000000000000000000000000000000000000000", + "ty": 29 } }, - "name": null + "name": "nodes_map" }, { "layout": { "cell": { "key": "0x0d00000000000000000000000000000000000000000000000000000000000000", - "ty": 11 + "ty": 31 } }, - "name": null + "name": "cluster_v_nodes_map" } ] } }, - "name": "accounts" + "name": "topology" }, { "layout": { @@ -2917,60 +4049,24 @@ "layout": { "cell": { "key": "0x0e00000000000000000000000000000000000000000000000000000000000000", - "ty": 30 + "ty": 32 } }, - "name": null - } - ] - } - }, - "name": "perms" - }, - { - "layout": { - "struct": { - "fields": [ + "name": "accounts" + }, { "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0f00000000000000000000000000000000000000000000000000000000000000", - "ty": 8 - } - }, - "name": "network_fee_bp" - }, - { - "layout": { - "cell": { - "key": "0x1000000000000000000000000000000000000000000000000000000000000000", - "ty": 2 - } - }, - "name": "network_fee_destination" - }, - { - "layout": { - "cell": { - "key": "0x1100000000000000000000000000000000000000000000000000000000000000", - "ty": 8 - } - }, - "name": "cluster_management_fee_bp" - } - ] + "cell": { + "key": "0x0f00000000000000000000000000000000000000000000000000000000000000", + "ty": 15 } }, - "name": null + "name": "accounts_keys" } ] } }, - "name": "network_fee" + "name": "accounts" }, { "layout": { @@ -2979,8 +4075,8 @@ { "layout": { "cell": { - "key": "0x1200000000000000000000000000000000000000000000000000000000000000", - "ty": 2 + "key": "0x1000000000000000000000000000000000000000000000000000000000000000", + "ty": 9 } }, "name": "operator_id" @@ -2988,8 +4084,8 @@ { "layout": { "cell": { - "key": "0x1300000000000000000000000000000000000000000000000000000000000000", - "ty": 32 + "key": "0x1100000000000000000000000000000000000000000000000000000000000000", + "ty": 34 } }, "name": "commits" @@ -2997,8 +4093,8 @@ { "layout": { "cell": { - "key": "0x1400000000000000000000000000000000000000000000000000000000000000", - "ty": 37 + "key": "0x1200000000000000000000000000000000000000000000000000000000000000", + "ty": 39 } }, "name": "validated_commits" @@ -3010,8 +4106,8 @@ { "layout": { "cell": { - "key": "0x1500000000000000000000000000000000000000000000000000000000000000", - "ty": 20 + "key": "0x1300000000000000000000000000000000000000000000000000000000000000", + "ty": 28 } }, "name": "start" @@ -3019,8 +4115,8 @@ { "layout": { "cell": { - "key": "0x1600000000000000000000000000000000000000000000000000000000000000", - "ty": 20 + "key": "0x1400000000000000000000000000000000000000000000000000000000000000", + "ty": 28 } }, "name": "interval" @@ -3028,8 +4124,8 @@ { "layout": { "cell": { - "key": "0x1700000000000000000000000000000000000000000000000000000000000000", - "ty": 20 + "key": "0x1500000000000000000000000000000000000000000000000000000000000000", + "ty": 28 } }, "name": "commit_duration" @@ -3037,8 +4133,8 @@ { "layout": { "cell": { - "key": "0x1800000000000000000000000000000000000000000000000000000000000000", - "ty": 20 + "key": "0x1600000000000000000000000000000000000000000000000000000000000000", + "ty": 28 } }, "name": "validation_duration" @@ -3060,20 +4156,20 @@ { "layout": { "cell": { - "key": "0x1900000000000000000000000000000000000000000000000000000000000000", - "ty": 2 + "key": "0x1700000000000000000000000000000000000000000000000000000000000000", + "ty": 12 } }, - "name": "admin" + "name": "protocol_fee_bp" }, { "layout": { "cell": { - "key": "0x1a00000000000000000000000000000000000000000000000000000000000000", - "ty": 5 + "key": "0x1800000000000000000000000000000000000000000000000000000000000000", + "ty": 9 } }, - "name": "fee_bp" + "name": "protocol_fee_destination" }, { "layout": { @@ -3082,8 +4178,8 @@ { "layout": { "cell": { - "key": "0x1b00000000000000000000000000000000000000000000000000000000000000", - "ty": 8 + "key": "0x1900000000000000000000000000000000000000000000000000000000000000", + "ty": 12 } }, "name": null @@ -3092,29 +4188,65 @@ } }, "name": "revenues" - } - ] - } - }, - "name": "protocol" - }, - { - "layout": { - "struct": { - "fields": [ + }, { "layout": { - "cell": { - "key": "0x1c00000000000000000000000000000000000000000000000000000000000000", - "ty": 39 + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x1a00000000000000000000000000000000000000000000000000000000000000", + "ty": 12 + } + }, + "name": "rate" + } + ] + } + }, + "name": "curr_converter" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x1b00000000000000000000000000000000000000000000000000000000000000", + "ty": 12 + } + }, + "name": "network_fee_bp" + }, + { + "layout": { + "cell": { + "key": "0x1c00000000000000000000000000000000000000000000000000000000000000", + "ty": 9 + } + }, + "name": "network_fee_destination" + }, + { + "layout": { + "cell": { + "key": "0x1d00000000000000000000000000000000000000000000000000000000000000", + "ty": 12 + } + }, + "name": "cluster_management_fee_bp" + } + ] } }, - "name": null + "name": "network_fee_config" } ] } }, - "name": "topology" + "name": "protocol" } ] } @@ -3122,103 +4254,94 @@ "types": [ { "id": 0, - "type": { - "def": { - "sequence": { - "type": 1 - } - } - } - }, - { - "id": 1, "type": { "def": { "composite": { "fields": [ { - "name": "owner_id", - "type": 2, - "typeName": "AccountId" - }, - { - "name": "cluster_id", - "type": 5, - "typeName": "ClusterId" - }, - { - "name": "flow", - "type": 6, - "typeName": "Flow" - }, - { - "name": "resource_reserved", - "type": 5, - "typeName": "Resource" - }, - { - "name": "public_availability", - "type": 9, - "typeName": "bool" - }, - { - "name": "resource_consumption_cap", - "type": 5, - "typeName": "Resource" + "name": "offset_key", + "type": 4, + "typeName": "Key" } ] } }, + "params": [ + { + "name": "K", + "type": 1 + }, + { + "name": "V", + "type": 3 + } + ], "path": [ - "ddc_bucket", - "ddc_bucket", - "bucket", - "entity", - "Bucket" + "ink_storage", + "lazy", + "mapping", + "Mapping" ] } }, + { + "id": 1, + "type": { + "def": { + "sequence": { + "type": 2 + } + } + } + }, { "id": 2, + "type": { + "def": { + "primitive": "u8" + } + } + }, + { + "id": 3, + "type": { + "def": { + "primitive": "bool" + } + } + }, + { + "id": 4, "type": { "def": { "composite": { "fields": [ { - "type": 3, + "type": 5, "typeName": "[u8; 32]" } ] } }, "path": [ - "ink_env", - "types", - "AccountId" + "ink_primitives", + "Key" ] } }, { - "id": 3, + "id": 5, "type": { "def": { "array": { "len": 32, - "type": 4 + "type": 2 } } } }, { - "id": 4, - "type": { - "def": { - "primitive": "u8" - } - } - }, - { - "id": 5, + "id": 6, "type": { "def": { "primitive": "u32" @@ -3226,46 +4349,151 @@ } }, { - "id": 6, + "id": 7, "type": { "def": { "composite": { "fields": [ { - "name": "from", - "type": 2, - "typeName": "AccountId" - }, - { - "name": "schedule", - "type": 7, - "typeName": "Schedule" + "name": "offset_key", + "type": 4, + "typeName": "Key" } ] } }, + "params": [ + { + "name": "K", + "type": 6 + }, + { + "name": "V", + "type": 8 + } + ], "path": [ - "ddc_bucket", - "ddc_bucket", - "flow", - "Flow" + "ink_storage", + "lazy", + "mapping", + "Mapping" ] } }, { - "id": 7, + "id": 8, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "owner_id", + "type": 9, + "typeName": "AccountId" + }, + { + "name": "cluster_id", + "type": 6, + "typeName": "ClusterId" + }, + { + "name": "flow", + "type": 10, + "typeName": "Flow" + }, + { + "name": "resource_reserved", + "type": 6, + "typeName": "Resource" + }, + { + "name": "public_availability", + "type": 3, + "typeName": "bool" + }, + { + "name": "resource_consumption_cap", + "type": 6, + "typeName": "Resource" + }, + { + "name": "bucket_params", + "type": 13, + "typeName": "BucketParams" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "bucket", + "entity", + "Bucket" + ] + } + }, + { + "id": 9, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 5, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_env", + "types", + "AccountId" + ] + } + }, + { + "id": 10, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "from", + "type": 9, + "typeName": "AccountId" + }, + { + "name": "schedule", + "type": 11, + "typeName": "Schedule" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "flow", + "Flow" + ] + } + }, + { + "id": 11, "type": { "def": { "composite": { "fields": [ { "name": "rate", - "type": 8, + "type": 12, "typeName": "Balance" }, { "name": "offset", - "type": 8, + "type": 12, "typeName": "Balance" } ] @@ -3280,7 +4508,7 @@ } }, { - "id": 8, + "id": 12, "type": { "def": { "primitive": "u128" @@ -3288,22 +4516,22 @@ } }, { - "id": 9, + "id": 13, "type": { "def": { - "primitive": "bool" + "primitive": "str" } } }, { - "id": 10, + "id": 14, "type": { "def": { "composite": { "fields": [ { "name": "offset_key", - "type": 12, + "type": 4, "typeName": "Key" } ] @@ -3312,11 +4540,11 @@ "params": [ { "name": "K", - "type": 5 + "type": 6 }, { "name": "V", - "type": 11 + "type": 15 } ], "path": [ @@ -3328,101 +4556,101 @@ } }, { - "id": 11, + "id": 15, "type": { "def": { "sequence": { - "type": 2 + "type": 9 } } } }, { - "id": 12, + "id": 16, "type": { "def": { "composite": { "fields": [ { - "type": 3, - "typeName": "[u8; 32]" + "name": "offset_key", + "type": 4, + "typeName": "Key" } ] } }, + "params": [ + { + "name": "K", + "type": 6 + }, + { + "name": "V", + "type": 17 + } + ], "path": [ - "ink_primitives", - "Key" + "ink_storage", + "lazy", + "mapping", + "Mapping" ] } }, { - "id": 13, - "type": { - "def": { - "sequence": { - "type": 14 - } - } - } - }, - { - "id": 14, - "type": { - "def": { - "primitive": "str" - } - } - }, - { - "id": 15, - "type": { - "def": { - "sequence": { - "type": 16 - } - } - } - }, - { - "id": 16, + "id": 17, "type": { "def": { "composite": { "fields": [ { "name": "manager_id", - "type": 2, + "type": 9, "typeName": "AccountId" }, + { + "name": "cluster_params", + "type": 13, + "typeName": "ClusterParams" + }, + { + "name": "nodes_keys", + "type": 15, + "typeName": "Vec" + }, { "name": "resource_per_v_node", - "type": 5, + "type": 6, "typeName": "Resource" }, { "name": "resource_used", - "type": 5, + "type": 6, "typeName": "Resource" }, { "name": "revenues", - "type": 17, + "type": 18, "typeName": "Cash" }, { - "name": "node_keys", - "type": 11, - "typeName": "Vec" + "name": "total_rent", + "type": 12, + "typeName": "Balance" }, { - "name": "v_nodes", + "name": "cdn_nodes_keys", + "type": 15, + "typeName": "Vec" + }, + { + "name": "cdn_revenues", "type": 18, - "typeName": "Vec>" + "typeName": "Cash" }, { - "name": "total_rent", - "type": 8, + "name": "cdn_usd_per_gb", + "type": 12, "typeName": "Balance" } ] @@ -3438,14 +4666,14 @@ } }, { - "id": 17, + "id": 18, "type": { "def": { "composite": { "fields": [ { "name": "value", - "type": 8, + "type": 12, "typeName": "Balance" } ] @@ -3459,74 +4687,68 @@ ] } }, - { - "id": 18, - "type": { - "def": { - "sequence": { - "type": 19 - } - } - } - }, { "id": 19, "type": { "def": { - "sequence": { + "composite": { + "fields": [ + { + "name": "offset_key", + "type": 4, + "typeName": "Key" + } + ] + } + }, + "params": [ + { + "name": "K", + "type": 9 + }, + { + "name": "V", "type": 20 } - } + ], + "path": [ + "ink_storage", + "lazy", + "mapping", + "Mapping" + ] } }, { "id": 20, - "type": { - "def": { - "primitive": "u64" - } - } - }, - { - "id": 21, - "type": { - "def": { - "sequence": { - "type": 22 - } - } - } - }, - { - "id": 22, "type": { "def": { "composite": { "fields": [ { - "name": "manager_id", - "type": 2, - "typeName": "AccountId" + "name": "provider_id", + "type": 9, + "typeName": "ProviderId" }, { - "name": "cdn_nodes", - "type": 11, - "typeName": "Vec" + "name": "undistributed_payment", + "type": 12, + "typeName": "Balance" }, { - "name": "resources_used", - "type": 5, - "typeName": "Resource" + "name": "cdn_node_params", + "type": 13, + "typeName": "CdnNodeParams" }, { - "name": "revenues", - "type": 17, - "typeName": "Cash" + "name": "cluster_id", + "type": 21, + "typeName": "Option" }, { - "name": "usd_per_gb", - "type": 8, - "typeName": "Balance" + "name": "status_in_cluster", + "type": 22, + "typeName": "Option" } ] } @@ -3534,161 +4756,87 @@ "path": [ "ddc_bucket", "ddc_bucket", - "cdn_cluster", + "cdn_node", "entity", - "CdnCluster" + "CdnNode" ] } }, { - "id": 23, + "id": 21, "type": { "def": { - "composite": { - "fields": [ + "variant": { + "variants": [ { - "name": "offset_key", - "type": 12, - "typeName": "Key" + "index": 0, + "name": "None" + }, + { + "fields": [ + { + "type": 6 + } + ], + "index": 1, + "name": "Some" } ] } }, "params": [ { - "name": "K", - "type": 2 - }, - { - "name": "V", - "type": 24 + "name": "T", + "type": 6 } ], "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" + "Option" ] } }, { - "id": 24, + "id": 22, "type": { "def": { - "composite": { - "fields": [ - { - "name": "provider_id", - "type": 2, - "typeName": "ProviderId" - }, + "variant": { + "variants": [ { - "name": "undistributed_payment", - "type": 8, - "typeName": "Balance" + "index": 0, + "name": "None" }, { - "name": "cdn_node_params", - "type": 14, - "typeName": "CdnNodeParams" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cdn_node", - "entity", - "CdnNode" - ] - } - }, - { - "id": 25, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 12, - "typeName": "Key" + "fields": [ + { + "type": 23 + } + ], + "index": 1, + "name": "Some" } ] } }, "params": [ { - "name": "K", - "type": 2 - }, - { - "name": "V", - "type": 26 + "name": "T", + "type": 23 } ], "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 26, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "provider_id", - "type": 2, - "typeName": "ProviderId" - }, - { - "name": "rent_per_month", - "type": 8, - "typeName": "Balance" - }, - { - "name": "free_resource", - "type": 5, - "typeName": "Resource" - }, - { - "name": "status", - "type": 27, - "typeName": "NodeStatusInCluster" - }, - { - "name": "node_params", - "type": 14, - "typeName": "NodeParams" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "node", - "entity", - "Node" + "Option" ] } }, { - "id": 27, + "id": 23, "type": { "def": { "variant": { "variants": [ { "index": 0, - "name": "UNKNOWN" + "name": "ADDING" }, { "index": 1, @@ -3696,14 +4844,10 @@ }, { "index": 2, - "name": "ADDING" - }, - { - "index": 3, "name": "DELETING" }, { - "index": 4, + "index": 3, "name": "OFFLINE" } ] @@ -3719,14 +4863,14 @@ } }, { - "id": 28, + "id": 24, "type": { "def": { "composite": { "fields": [ { "name": "offset_key", - "type": 12, + "type": 4, "typeName": "Key" } ] @@ -3735,11 +4879,11 @@ "params": [ { "name": "K", - "type": 2 + "type": 9 }, { "name": "V", - "type": 29 + "type": 25 } ], "path": [ @@ -3751,40 +4895,40 @@ } }, { - "id": 29, + "id": 25, "type": { "def": { "composite": { "fields": [ { - "name": "deposit", - "type": 17, - "typeName": "Cash" + "name": "provider_id", + "type": 9, + "typeName": "ProviderId" }, { - "name": "bonded", - "type": 17, - "typeName": "Cash" + "name": "rent_per_month", + "type": 12, + "typeName": "Balance" }, { - "name": "negative", - "type": 17, - "typeName": "Cash" + "name": "free_resource", + "type": 6, + "typeName": "Resource" }, { - "name": "unbonded_amount", - "type": 17, - "typeName": "Cash" + "name": "node_params", + "type": 13, + "typeName": "NodeParams" }, { - "name": "unbonded_timestamp", - "type": 20, - "typeName": "u64" + "name": "cluster_id", + "type": 21, + "typeName": "Option" }, { - "name": "payable_schedule", - "type": 7, - "typeName": "Schedule" + "name": "status_in_cluster", + "type": 22, + "typeName": "Option" } ] } @@ -3792,21 +4936,21 @@ "path": [ "ddc_bucket", "ddc_bucket", - "account", + "node", "entity", - "Account" + "Node" ] } }, { - "id": 30, + "id": 26, "type": { "def": { "composite": { "fields": [ { "name": "offset_key", - "type": 12, + "type": 4, "typeName": "Key" } ] @@ -3815,11 +4959,11 @@ "params": [ { "name": "K", - "type": 31 + "type": 9 }, { "name": "V", - "type": 9 + "type": 27 } ], "path": [ @@ -3831,24 +4975,32 @@ } }, { - "id": 31, + "id": 27, "type": { "def": { "sequence": { - "type": 4 + "type": 28 } } } }, { - "id": 32, + "id": 28, + "type": { + "def": { + "primitive": "u64" + } + } + }, + { + "id": 29, "type": { "def": { "composite": { "fields": [ { "name": "offset_key", - "type": 12, + "type": 4, "typeName": "Key" } ] @@ -3857,11 +5009,11 @@ "params": [ { "name": "K", - "type": 2 + "type": 30 }, { "name": "V", - "type": 33 + "type": 9 } ], "path": [ @@ -3873,93 +5025,137 @@ } }, { - "id": 33, - "type": { - "def": { - "sequence": { - "type": 34 - } - } - } - }, - { - "id": 34, + "id": 30, "type": { "def": { "tuple": [ - 2, - 35 + 6, + 28 ] } } }, { - "id": 35, + "id": 31, "type": { "def": { "composite": { "fields": [ { - "name": "hash", - "type": 36, - "typeName": "Hash" - }, - { - "name": "total_logs", - "type": 8, - "typeName": "u128" - }, - { - "name": "from_timestamp", - "type": 20, - "typeName": "u64" - }, - { - "name": "to_timestamp", - "type": 20, - "typeName": "u64" + "name": "offset_key", + "type": 4, + "typeName": "Key" } ] } }, + "params": [ + { + "name": "K", + "type": 6 + }, + { + "name": "V", + "type": 27 + } + ], "path": [ - "ddc_bucket", - "ddc_bucket", - "committer", - "store", - "Commit" + "ink_storage", + "lazy", + "mapping", + "Mapping" ] } }, { - "id": 36, + "id": 32, "type": { "def": { "composite": { "fields": [ { - "type": 3, - "typeName": "[u8; 32]" + "name": "offset_key", + "type": 4, + "typeName": "Key" } ] } }, - "path": [ - "ink_env", - "types", - "Hash" + "params": [ + { + "name": "K", + "type": 9 + }, + { + "name": "V", + "type": 33 + } + ], + "path": [ + "ink_storage", + "lazy", + "mapping", + "Mapping" ] } }, { - "id": 37, + "id": 33, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "deposit", + "type": 18, + "typeName": "Cash" + }, + { + "name": "bonded", + "type": 18, + "typeName": "Cash" + }, + { + "name": "negative", + "type": 18, + "typeName": "Cash" + }, + { + "name": "unbonded_amount", + "type": 18, + "typeName": "Cash" + }, + { + "name": "unbonded_timestamp", + "type": 28, + "typeName": "u64" + }, + { + "name": "payable_schedule", + "type": 11, + "typeName": "Schedule" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "account", + "entity", + "Account" + ] + } + }, + { + "id": 34, "type": { "def": { "composite": { "fields": [ { "name": "offset_key", - "type": 12, + "type": 4, "typeName": "Key" } ] @@ -3968,11 +5164,11 @@ "params": [ { "name": "K", - "type": 2 + "type": 9 }, { "name": "V", - "type": 38 + "type": 35 } ], "path": [ @@ -3984,16 +5180,84 @@ } }, { - "id": 38, + "id": 35, + "type": { + "def": { + "sequence": { + "type": 36 + } + } + } + }, + { + "id": 36, "type": { "def": { "tuple": [ - 20, - 20 + 9, + 37 ] } } }, + { + "id": 37, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "hash", + "type": 38, + "typeName": "Hash" + }, + { + "name": "total_logs", + "type": 12, + "typeName": "u128" + }, + { + "name": "from_timestamp", + "type": 28, + "typeName": "u64" + }, + { + "name": "to_timestamp", + "type": 28, + "typeName": "u64" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "committer", + "store", + "Commit" + ] + } + }, + { + "id": 38, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 5, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_env", + "types", + "Hash" + ] + } + }, { "id": 39, "type": { @@ -4002,7 +5266,7 @@ "fields": [ { "name": "offset_key", - "type": 12, + "type": 4, "typeName": "Key" } ] @@ -4011,11 +5275,11 @@ "params": [ { "name": "K", - "type": 40 + "type": 9 }, { "name": "V", - "type": 2 + "type": 40 } ], "path": [ @@ -4031,8 +5295,8 @@ "type": { "def": { "tuple": [ - 5, - 20 + 28, + 28 ] } } @@ -4050,7 +5314,7 @@ { "fields": [ { - "type": 2 + "type": 9 } ], "index": 1, @@ -4062,7 +5326,7 @@ "params": [ { "name": "T", - "type": 2 + "type": 9 } ], "path": [ @@ -4072,14 +5336,6 @@ }, { "id": 42, - "type": { - "def": { - "tuple": [] - } - } - }, - { - "id": 43, "type": { "def": { "variant": { @@ -4087,7 +5343,7 @@ { "fields": [ { - "type": 44 + "type": 6 } ], "index": 0, @@ -4096,7 +5352,7 @@ { "fields": [ { - "type": 46 + "type": 43 } ], "index": 1, @@ -4108,11 +5364,11 @@ "params": [ { "name": "T", - "type": 44 + "type": 6 }, { "name": "E", - "type": 46 + "type": 43 } ], "path": [ @@ -4121,40 +5377,232 @@ } }, { - "id": 44, + "id": 43, "type": { "def": { - "composite": { - "fields": [ + "variant": { + "variants": [ { - "name": "bucket_id", - "type": 5, - "typeName": "BucketId" + "index": 0, + "name": "NodeDoesNotExist" }, { - "name": "bucket", - "type": 45, - "typeName": "BucketInStatus" + "index": 1, + "name": "CdnNodeDoesNotExist" }, { - "name": "params", - "type": 14, - "typeName": "BucketParams" + "index": 2, + "name": "NodeAlreadyExists" }, { - "name": "writer_ids", - "type": 11, - "typeName": "Vec" + "index": 3, + "name": "CdnNodeAlreadyExists" }, { - "name": "reader_ids", - "type": 11, - "typeName": "Vec" + "index": 4, + "name": "AccountDoesNotExist" }, { - "name": "rent_covered_until_ms", - "type": 20, - "typeName": "u64" + "index": 5, + "name": "ParamsDoesNotExist" + }, + { + "index": 6, + "name": "ParamsSizeExceedsLimit" + }, + { + "index": 7, + "name": "OnlyOwner" + }, + { + "index": 8, + "name": "OnlyNodeProvider" + }, + { + "index": 9, + "name": "OnlyCdnNodeProvider" + }, + { + "index": 10, + "name": "OnlyClusterManager" + }, + { + "index": 11, + "name": "OnlyTrustedClusterManager" + }, + { + "index": 12, + "name": "OnlySuperAdmin" + }, + { + "index": 13, + "name": "OnlyClusterManagerOrNodeProvider" + }, + { + "index": 14, + "name": "OnlyClusterManagerOrCdnNodeProvider" + }, + { + "index": 15, + "name": "Unauthorized" + }, + { + "index": 16, + "name": "ClusterDoesNotExist" + }, + { + "index": 17, + "name": "ClusterIsNotEmpty" + }, + { + "fields": [ + { + "type": 6, + "typeName": "ClusterId" + } + ], + "index": 18, + "name": "TopologyIsNotCreated" + }, + { + "index": 19, + "name": "TopologyAlreadyExists" + }, + { + "index": 20, + "name": "NodesSizeExceedsLimit" + }, + { + "index": 21, + "name": "CdnNodesSizeExceedsLimit" + }, + { + "index": 22, + "name": "VNodesSizeExceedsLimit" + }, + { + "index": 23, + "name": "AccountsSizeExceedsLimit" + }, + { + "fields": [ + { + "type": 6, + "typeName": "ClusterId" + } + ], + "index": 24, + "name": "NodeIsNotAddedToCluster" + }, + { + "fields": [ + { + "type": 6, + "typeName": "ClusterId" + } + ], + "index": 25, + "name": "NodeIsAddedToCluster" + }, + { + "fields": [ + { + "type": 6, + "typeName": "ClusterId" + } + ], + "index": 26, + "name": "CdnNodeIsNotAddedToCluster" + }, + { + "fields": [ + { + "type": 6, + "typeName": "ClusterId" + } + ], + "index": 27, + "name": "CdnNodeIsAddedToCluster" + }, + { + "fields": [ + { + "type": 6, + "typeName": "ClusterId" + } + ], + "index": 28, + "name": "VNodeDoesNotExistsInCluster" + }, + { + "fields": [ + { + "type": 6, + "typeName": "ClusterId" + }, + { + "type": 28, + "typeName": "VNodeToken" + } + ], + "index": 29, + "name": "VNodeIsNotAssignedToNode" + }, + { + "fields": [ + { + "type": 9, + "typeName": "NodeKey" + } + ], + "index": 30, + "name": "VNodeIsAlreadyAssignedToNode" + }, + { + "fields": [ + { + "type": 6, + "typeName": "ClusterId" + }, + { + "type": 9, + "typeName": "NodeKey" + } + ], + "index": 31, + "name": "AtLeastOneVNodeHasToBeAssigned" + }, + { + "index": 32, + "name": "NodeProviderIsNotSuperAdmin" + }, + { + "index": 33, + "name": "CdnNodeOwnerIsNotSuperAdmin" + }, + { + "index": 34, + "name": "BucketDoesNotExist" + }, + { + "index": 35, + "name": "BondingPeriodNotFinished" + }, + { + "index": 36, + "name": "TransferFailed" + }, + { + "index": 37, + "name": "InsufficientBalance" + }, + { + "index": 38, + "name": "InsufficientResources" + }, + { + "index": 39, + "name": "EraSettingFailed" } ] } @@ -4162,55 +5610,60 @@ "path": [ "ddc_bucket", "ddc_bucket", - "bucket", - "entity", - "BucketStatus" + "Error" ] } }, { - "id": 45, + "id": 44, "type": { "def": { - "composite": { - "fields": [ - { - "name": "owner_id", - "type": 2, - "typeName": "AccountId" - }, - { - "name": "cluster_id", - "type": 5, - "typeName": "ClusterId" - }, - { - "name": "resource_reserved", - "type": 5, - "typeName": "Resource" - }, + "variant": { + "variants": [ { - "name": "public_availability", - "type": 9, - "typeName": "bool" + "fields": [ + { + "type": 45 + } + ], + "index": 0, + "name": "Ok" }, { - "name": "resource_consumption_cap", - "type": 5, - "typeName": "Resource" + "fields": [ + { + "type": 43 + } + ], + "index": 1, + "name": "Err" } ] } }, + "params": [ + { + "name": "T", + "type": 45 + }, + { + "name": "E", + "type": 43 + } + ], "path": [ - "ddc_bucket", - "ddc_bucket", - "bucket", - "entity", - "BucketInStatus" + "Result" ] } }, + { + "id": 45, + "type": { + "def": { + "tuple": [] + } + } + }, { "id": 46, "type": { @@ -4218,96 +5671,119 @@ "variant": { "variants": [ { + "fields": [ + { + "type": 47 + } + ], "index": 0, - "name": "BucketDoesNotExist" + "name": "Ok" }, { + "fields": [ + { + "type": 43 + } + ], "index": 1, - "name": "ClusterDoesNotExist" - }, - { - "index": 2, - "name": "ParamsSizeExceedsLimit" - }, - { - "index": 3, - "name": "VNodeDoesNotExist" - }, - { - "index": 4, - "name": "BondingPeriodNotFinished" - }, - { - "index": 5, - "name": "BucketClusterAlreadyConnected" - }, - { - "index": 6, - "name": "BucketClusterNotSetup" - }, - { - "index": 7, - "name": "NodeDoesNotExist" - }, - { - "index": 8, - "name": "CdnNodeDoesNotExist" - }, - { - "index": 9, - "name": "NodeAlreadyExists" - }, - { - "index": 10, - "name": "CdnNodeAlreadyExists" - }, - { - "index": 11, - "name": "FlowDoesNotExist" - }, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 47 + }, + { + "name": "E", + "type": 43 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 47, + "type": { + "def": { + "composite": { + "fields": [ { - "index": 12, - "name": "AccountDoesNotExist" + "name": "bucket_id", + "type": 6, + "typeName": "BucketId" }, { - "index": 13, - "name": "ParamsDoesNotExist" + "name": "bucket", + "type": 48, + "typeName": "BucketInStatus" }, { - "index": 14, - "name": "UnauthorizedProvider" + "name": "params", + "type": 13, + "typeName": "BucketParams" }, { - "index": 15, - "name": "OnlyOwner" + "name": "writer_ids", + "type": 15, + "typeName": "Vec" }, { - "index": 16, - "name": "UnauthorizedClusterManager" + "name": "reader_ids", + "type": 15, + "typeName": "Vec" }, { - "index": 17, - "name": "OnlyTrustedClusterManager" - }, + "name": "rent_covered_until_ms", + "type": 28, + "typeName": "u64" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "bucket", + "entity", + "BucketStatus" + ] + } + }, + { + "id": 48, + "type": { + "def": { + "composite": { + "fields": [ { - "index": 18, - "name": "TransferFailed" + "name": "owner_id", + "type": 9, + "typeName": "AccountId" }, { - "index": 19, - "name": "InsufficientBalance" + "name": "cluster_id", + "type": 6, + "typeName": "ClusterId" }, { - "index": 20, - "name": "InsufficientResources" + "name": "resource_reserved", + "type": 6, + "typeName": "Resource" }, { - "index": 21, - "name": "Unauthorized" + "name": "public_availability", + "type": 3, + "typeName": "bool" }, { - "index": 22, - "name": "UnknownNode" + "name": "resource_consumption_cap", + "type": 6, + "typeName": "Resource" } ] } @@ -4315,33 +5791,45 @@ "path": [ "ddc_bucket", "ddc_bucket", - "Error" + "bucket", + "entity", + "BucketInStatus" ] } }, { - "id": 47, + "id": 49, "type": { "def": { "tuple": [ - 48, - 5 + 50, + 6 ] } } }, { - "id": 48, + "id": 50, "type": { "def": { "sequence": { - "type": 44 + "type": 47 } } } }, { - "id": 49, + "id": 51, + "type": { + "def": { + "sequence": { + "type": 8 + } + } + } + }, + { + "id": 52, "type": { "def": { "variant": { @@ -4349,7 +5837,7 @@ { "fields": [ { - "type": 50 + "type": 53 } ], "index": 0, @@ -4358,7 +5846,7 @@ { "fields": [ { - "type": 46 + "type": 43 } ], "index": 1, @@ -4370,11 +5858,11 @@ "params": [ { "name": "T", - "type": 50 + "type": 53 }, { "name": "E", - "type": 46 + "type": 43 } ], "path": [ @@ -4383,25 +5871,25 @@ } }, { - "id": 50, + "id": 53, "type": { "def": { "composite": { "fields": [ { "name": "cluster_id", - "type": 5, + "type": 6, "typeName": "ClusterId" }, { "name": "cluster", - "type": 16, + "type": 17, "typeName": "Cluster" }, { - "name": "params", - "type": 14, - "typeName": "Params" + "name": "cluster_v_nodes", + "type": 27, + "typeName": "Vec" } ] } @@ -4415,44 +5903,13 @@ ] } }, - { - "id": 51, - "type": { - "def": { - "tuple": [ - 52, - 5 - ] - } - } - }, - { - "id": 52, - "type": { - "def": { - "sequence": { - "type": 50 - } - } - } - }, - { - "id": 53, - "type": { - "def": { - "sequence": { - "type": 54 - } - } - } - }, { "id": 54, "type": { "def": { "tuple": [ - 2, - 8 + 55, + 6 ] } } @@ -4462,24 +5919,13 @@ "type": { "def": { "sequence": { - "type": 56 + "type": 53 } } } }, { "id": 56, - "type": { - "def": { - "tuple": [ - 5, - 5 - ] - } - } - }, - { - "id": 57, "type": { "def": { "variant": { @@ -4487,7 +5933,7 @@ { "fields": [ { - "type": 58 + "type": 12 } ], "index": 0, @@ -4496,7 +5942,7 @@ { "fields": [ { - "type": 46 + "type": 43 } ], "index": 1, @@ -4508,11 +5954,11 @@ "params": [ { "name": "T", - "type": 58 + "type": 12 }, { "name": "E", - "type": 46 + "type": 43 } ], "path": [ @@ -4521,54 +5967,47 @@ } }, { - "id": 58, + "id": 57, "type": { "def": { - "composite": { - "fields": [ - { - "name": "cluster_id", - "type": 5, - "typeName": "ClusterId" - }, - { - "name": "cluster", - "type": 22, - "typeName": "CdnCluster" - } - ] + "sequence": { + "type": 58 } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cdn_cluster", - "entity", - "CdnClusterStatus" - ] + } } }, { - "id": 59, + "id": 58, "type": { "def": { "tuple": [ - 60, - 5 + 9, + 12 ] } } }, { - "id": 60, + "id": 59, "type": { "def": { "sequence": { - "type": 58 + "type": 60 } } } }, + { + "id": 60, + "type": { + "def": { + "tuple": [ + 6, + 6 + ] + } + } + }, { "id": 61, "type": { @@ -4577,22 +6016,22 @@ "fields": [ { "name": "start", - "type": 20, + "type": 28, "typeName": "u64" }, { "name": "interval", - "type": 20, + "type": 28, "typeName": "u64" }, { "name": "commit_duration", - "type": 20, + "type": 28, "typeName": "u64" }, { "name": "validation_duration", - "type": 20, + "type": 28, "typeName": "u64" } ] @@ -4615,7 +6054,7 @@ "fields": [ { "name": "current_era", - "type": 20, + "type": 28, "typeName": "u64" }, { @@ -4625,17 +6064,17 @@ }, { "name": "previous_era", - "type": 20, + "type": 28, "typeName": "u64" }, { "name": "prev_era_from_timestamp", - "type": 20, + "type": 28, "typeName": "u64" }, { "name": "prev_era_to_timestamp", - "type": 20, + "type": 28, "typeName": "u64" } ] @@ -4689,7 +6128,7 @@ { "fields": [ { - "type": 65 + "type": 9 } ], "index": 0, @@ -4698,7 +6137,7 @@ { "fields": [ { - "type": 46 + "type": 43 } ], "index": 1, @@ -4710,11 +6149,11 @@ "params": [ { "name": "T", - "type": 65 + "type": 9 }, { "name": "E", - "type": 46 + "type": 43 } ], "path": [ @@ -4724,18 +6163,60 @@ }, { "id": 65, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 66 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 43 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 66 + }, + { + "name": "E", + "type": 43 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 66, "type": { "def": { "composite": { "fields": [ { "name": "cdn_node_key", - "type": 2, + "type": 9, "typeName": "CdnNodeKey" }, { "name": "cdn_node", - "type": 24, + "type": 20, "typeName": "CdnNode" } ] @@ -4751,68 +6232,26 @@ } }, { - "id": 66, + "id": 67, "type": { "def": { "tuple": [ - 67, - 5 + 68, + 6 ] } } }, { - "id": 67, + "id": 68, "type": { "def": { "sequence": { - "type": 65 + "type": 66 } } } }, - { - "id": 68, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 42 - } - ], - "index": 0, - "name": "Ok" - }, - { - "fields": [ - { - "type": 46 - } - ], - "index": 1, - "name": "Err" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 42 - }, - { - "name": "E", - "type": 46 - } - ], - "path": [ - "Result" - ] - } - }, { "id": 69, "type": { @@ -4831,7 +6270,7 @@ { "fields": [ { - "type": 46 + "type": 43 } ], "index": 1, @@ -4847,7 +6286,7 @@ }, { "name": "E", - "type": 46 + "type": 43 } ], "path": [ @@ -4863,13 +6302,18 @@ "fields": [ { "name": "node_key", - "type": 2, + "type": 9, "typeName": "NodeKey" }, { "name": "node", - "type": 26, + "type": 25, "typeName": "Node" + }, + { + "name": "v_nodes", + "type": 27, + "typeName": "Vec" } ] } @@ -4889,7 +6333,7 @@ "def": { "tuple": [ 72, - 5 + 6 ] } } @@ -4913,7 +6357,7 @@ { "fields": [ { - "type": 29 + "type": 33 } ], "index": 0, @@ -4922,7 +6366,7 @@ { "fields": [ { - "type": 46 + "type": 43 } ], "index": 1, @@ -4934,11 +6378,11 @@ "params": [ { "name": "T", - "type": 29 + "type": 33 }, { "name": "E", - "type": 46 + "type": 43 } ], "path": [ @@ -4955,7 +6399,7 @@ { "fields": [ { - "type": 2, + "type": 9, "typeName": "AccountId" } ], @@ -4990,17 +6434,17 @@ "fields": [ { "name": "network_fee_bp", - "type": 8, + "type": 12, "typeName": "BasisPoints" }, { "name": "network_fee_destination", - "type": 2, + "type": 9, "typeName": "AccountId" }, { "name": "cluster_management_fee_bp", - "type": 8, + "type": 12, "typeName": "BasisPoints" } ] @@ -5009,8 +6453,9 @@ "path": [ "ddc_bucket", "ddc_bucket", - "network_fee", - "FeeConfig" + "protocol", + "store", + "NetworkFeeConfig" ] } } diff --git a/scripts/sdk/src/bucket/ddcBucket.js b/scripts/sdk/src/bucket/ddcBucket.js index 2414e1de..592c7a48 100644 --- a/scripts/sdk/src/bucket/ddcBucket.js +++ b/scripts/sdk/src/bucket/ddcBucket.js @@ -1,28 +1,134 @@ const _ = require("lodash"); -function findCreatedId(events, eventName) { +function findEvent(events, eventName) { const event = _.find(events, ["event.identifier", eventName]); - const id = _.get(event, "args[0]"); - return id && id.toString(); + if (!event) + throw new Error("Event '" + eventName + "' is not found"); + return event; } -function findCreatedNodeId(events) { - return findCreatedId(events, "NodeCreated"); +function findNodeCreatedEvent(events) { + const event = findEvent(events, "NodeCreated"); + const nodeKey = _.get(event, "args[0]").toString(); + const providerId = _.get(event, "args[1]").toString(); + const rentPerMonth = _.get(event, "args[2]").toNumber(); + const nodeParams = _.get(event, "args[3]").toString(); + return { nodeKey, providerId, rentPerMonth, nodeParams }; } -function findCreatedClusterId(events) { - return findCreatedId(events, "ClusterCreated"); +function findCdnNodeCreatedEvent(events) { + const event = findEvent(events, "CdnNodeCreated"); + const cdnNodeKey = _.get(event, "args[0]").toString(); + const providerId = _.get(event, "args[1]").toString(); + const cdnNodeParams = _.get(event, "args[2]").toString(); + const undistributedPayment = _.get(event, "args[3]").toNumber(); + return { cdnNodeKey, providerId, cdnNodeParams, undistributedPayment }; } -function findCreatedBucketId(events) { - return findCreatedId(events, "BucketCreated"); +function findClusterCreatedEvent(events) { + const event = findEvent(events, "ClusterCreated"); + const clusterId = _.get(event, "args[0]").toNumber(); + const managerId = _.get(event, "args[1]").toString(); + const clusterParams = _.get(event, "args[2]").toString(); + return { clusterId, managerId, clusterParams }; +} + +function findBucketCreatedEvent(events) { + const event = findEvent(events, "BucketCreated"); + const bucketId = _.get(event, "args[0]").toNumber(); + const ownerId = _.get(event, "args[1]").toString(); + return { bucketId, ownerId }; +} + +function findPermissionGrantedEvent(events) { + const event = findEvent(events, "PermissionGranted"); + const accountId = _.get(event, "args[0]").toString(); + const permission = _.get(event, "args[1]").toString(); + return { accountId, permission }; +} + +function findClusterReserveResourceEvent(events) { + const event = findEvent(events, "ClusterReserveResource"); + const clusterId = _.get(event, "args[0]").toNumber(); + const reserved = _.get(event, "args[1]").toNumber(); + return { clusterId, reserved }; +} + +function findClusterNodeStatusSetEvent(events) { + const event = findEvent(events, "ClusterNodeStatusSet"); + const nodeKey = _.get(event, "args[0]").toString(); + const clusterId = _.get(event, "args[1]").toNumber(); + const status = _.get(event, "args[2]").toString(); + return { nodeKey, clusterId, status }; +} + +function findClusterCdnNodeStatusSetEvent(events) { + const event = findEvent(events, "ClusterCdnNodeStatusSet"); + const cdnNodeKey = _.get(event, "args[0]").toString(); + const clusterId = _.get(event, "args[1]").toNumber(); + const status = _.get(event, "args[2]").toString(); + return { cdnNodeKey, clusterId, status }; +} + +function findClusterNodeAddedEvent(events) { + const event = findEvent(events, "ClusterNodeAdded"); + const clusterId = _.get(event, "args[0]").toNumber(); + const nodeKey = _.get(event, "args[1]").toString(); + return { nodeKey, clusterId }; +} + +function findClusterCdnNodeAddedEvent(events) { + const event = findEvent(events, "ClusterCdnNodeAdded"); + const clusterId = _.get(event, "args[0]").toNumber(); + const cdnNodeKey = _.get(event, "args[1]").toString(); + return { cdnNodeKey, clusterId }; +} + +function findDepositEvent(events) { + const event = findEvent(events, "Deposit"); + const accountId = _.get(event, "args[0]").toString(); + const value = _.get(event, "args[1]").toNumber(); + return { accountId, value }; +} + +function findBucketAllocatedEvent(events) { + const event = findEvent(events, "BucketAllocated"); + const bucketId = _.get(event, "args[0]").toNumber(); + const clusterId = _.get(event, "args[1]").toNumber(); + const resource = _.get(event, "args[2]").toNumber(); + return { bucketId, clusterId, resource }; +} + +function findBucketSettlePaymentEvent(events) { + const event = findEvent(events, "BucketSettlePayment"); + const bucketId = _.get(event, "args[0]").toNumber(); + const clusterId = _.get(event, "args[1]").toNumber(); + return { bucketId, clusterId }; +} + +function findClusterDistributeRevenuesEvent(events) { + const event = findEvent(events, "ClusterDistributeRevenues"); + const clusterId = _.get(event, "args[0]").toNumber(); + const providerId = _.get(event, "args[1]").toString(); + return { clusterId, providerId }; } module.exports = { - findCreatedId, - findCreatedNodeId, - findCreatedClusterId, - findCreatedBucketId, + findEvent, + findNodeCreatedEvent, + findCdnNodeCreatedEvent, + findClusterCreatedEvent, + findBucketCreatedEvent, + findPermissionGrantedEvent, + findClusterReserveResourceEvent, + findClusterNodeStatusSetEvent, + findClusterCdnNodeStatusSetEvent, + findClusterNodeAddedEvent, + findClusterCdnNodeAddedEvent, + findDepositEvent, + findBucketAllocatedEvent, + findBucketSettlePaymentEvent, + findClusterDistributeRevenuesEvent, }; diff --git a/scripts/sdk/src/config/index.js b/scripts/sdk/src/config/index.js index 20f45a51..978d861b 100644 --- a/scripts/sdk/src/config/index.js +++ b/scripts/sdk/src/config/index.js @@ -17,11 +17,10 @@ const TESTNET_DDC_NFT_REGISTRY_ADDR = "6VFZJT9Kox8iZN4DL27GNFCpfTWHXbDst2WC7jpiJ const TESTNET_CHAIN_NAME = "Cere Testnet"; const LOCAL_RPC_ENDPOINT = "ws://127.0.0.1:9944/"; -const LOCAL_DDC_BUCKET_ADDR = ""; +const LOCAL_DDC_BUCKET_ADDR = ""; // add your local address const LOCAL_DDC_NFT_REGISTRY_ADDR = ""; const LOCAL_CHAIN_NAME = "Development"; - module.exports = { ACTOR_SEED, EXPLORER_URL, diff --git a/scripts/sdk/src/deploymentRegistry.js b/scripts/sdk/src/deploymentRegistry.js index 9e88acfa..de060568 100644 --- a/scripts/sdk/src/deploymentRegistry.js +++ b/scripts/sdk/src/deploymentRegistry.js @@ -21,6 +21,11 @@ function initContracts() { config.TESTNET_DDC_BUCKET_ADDR ); + registerContract( + config.DDC_BUCKET_CONTRACT_NAME, + config.LOCAL_CHAIN_NAME, + config.LOCAL_DDC_BUCKET_ADDR + ); registerABI(config.DDC_NFT_REGISTRY_CONTRACT_NAME, ddcNftRegistryAbi); From f8b68ca28e3596aaf20b230487d64bd4ec0014d4 Mon Sep 17 00:00:00 2001 From: Denis Glotov Date: Tue, 27 Jun 2023 12:08:55 +0300 Subject: [PATCH 76/89] Init bucket contract script code (#78) --- bucket/scripts/.gitignore | 2 + bucket/scripts/config.js | 139 + bucket/scripts/init.js | 129 + bucket/scripts/metadata.json | 4959 ++++++++++++++++++++++++++++++ bucket/scripts/package-lock.json | 789 +++++ bucket/scripts/package.json | 8 + 6 files changed, 6026 insertions(+) create mode 100644 bucket/scripts/.gitignore create mode 100644 bucket/scripts/config.js create mode 100644 bucket/scripts/init.js create mode 100644 bucket/scripts/metadata.json create mode 100644 bucket/scripts/package-lock.json create mode 100644 bucket/scripts/package.json diff --git a/bucket/scripts/.gitignore b/bucket/scripts/.gitignore new file mode 100644 index 00000000..1929c324 --- /dev/null +++ b/bucket/scripts/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +secrets.txt diff --git a/bucket/scripts/config.js b/bucket/scripts/config.js new file mode 100644 index 00000000..0323cfe1 --- /dev/null +++ b/bucket/scripts/config.js @@ -0,0 +1,139 @@ +const GEN = 0x10000000000000000n; // UINT64_MAX + +export const config = { + devnet: { + ws_provider: "wss://archive.devnet.cere.network/ws", + contract_address: "6SfBsKbfPUTN35GCcqAHSMY4MemedK2A73VeJ34Z2FV6PB4r", + cluster: { + 1n: { + param: { replicationFactor: 3 }, + vnodes: [ [0n], [GEN / 4n], [GEN * 2n / 4n], [GEN * 3n / 4n] ], + storage_nodes: [1n, 2n, 3n, 4n], + }, + }, + storage_node_params: [ + { url: `https://node-0.v2.storage.devnet.cere.network` }, + { url: `https://node-1.v2.storage.devnet.cere.network` }, + { url: `https://node-2.v2.storage.devnet.cere.network` }, + { url: `https://node-3.v2.storage.devnet.cere.network` }, + ], + cdn_cluster: { + 0n: { + cdn_nodes: [1n, 2n, 3n, 4n], + }, + }, + cdn_node_params: [ + { + url: `https://node-0.v2.cdn.devnet.cere.network`, + publicKey: "0x1c4a1b081af8dd09096ebb6e7ad61dd549ac2931cdb2b1216589094ad71ca90b", + }, + { + url: `https://node-1.v2.cdn.devnet.cere.network`, + publicKey: "0x3ec2ec407053acdfe8137d7105e90294f2e0e5f5fe5420fd3172142671dbc25f", + }, + { + url: `https://node-2.v2.cdn.devnet.cere.network`, + publicKey: "0x20e448c403d3f009ec309394d3aab828c3dbf0d2cc8047f01dded984ec992b41", + }, + { + url: `https://node-3.v2.cdn.devnet.cere.network`, + publicKey: "0xd2f93cea79e37cfc9e5f78cd3e51b989afb1e257adcbbae00b8cd081539e9f13", + } + ], + }, + + testnet: { + ws_provider: "wss://archive.devnet.cere.network/ws", + // contract_address: "6R2PF5gzKYbNkNLymTr8YNeQgWqNkE6azspwaMLZF2UHc1sg", + contract_address: "6UWDf6rEgSDFRr1h2pMdCbifowTDK64yRkDR6nc3C1cjL82e", + cluster: { + 1n: { + storage_nodes: [1n, 2n, 3n], + vnodes: [ [0n], [GEN / 3n], [GEN * 2n / 3n] ], + param: { replicationFactor: 3 }, + }, + 2n: { + storage_nodes: [4n, 5n, 6n], + vnodes: [ [0n], [GEN / 3n], [GEN * 2n / 3n] ], + param: { replicationFactor: 3 }, + }, + }, + storage_node_params: [ + { url: `https://node-0.v2.us.storage.testnet.cere.network` }, + { url: `https://node-1.v2.us.storage.testnet.cere.network` }, + { url: `https://node-2.v2.us.storage.testnet.cere.network` }, + { url: `https://node-0.v2.eu.storage.testnet.cere.network` }, + { url: `https://node-1.v2.eu.storage.testnet.cere.network` }, + { url: `https://node-2.v2.eu.storage.testnet.cere.network` }, + ], + cdn_cluster: { + 0n: { + cdn_nodes: [1n, 2n], + }, + 1n: { + cdn_nodes: [3n, 4n], + }, + 2n: { + cdn_nodes: [5n, 6n], + }, + }, + cdn_node_params: [ + { + url: `https://node-0.v2.us.cdn.testnet.cere.network`, + publicKey: "0x089522cee0567ff8e072c9efbd5cb4e05fe47cdab8340816be9d6f60538e8645", + }, + { + url: `https://node-1.v2.us.cdn.testnet.cere.network`, + publicKey: "0x7693cbc6a6f3fff67d4eb29bb07bc018e1eee43618d03e6c0a91b0b3e79f272d", + }, + { + url: `https://node-0.v2.eu.cdn.testnet.cere.network`, + publicKey: "0xdce47cdd1da69c19261b72e3c58e93d78e49d1ac20a566b535cb9bcf9d197958", + }, + { + url: `https://node-1.v2.eu.cdn.testnet.cere.network`, + publicKey: "0xb8541743735ffba6877b214925a9ec07c813369bb36b49ee5849b1fea0f9dd55", + }, + { + url: `https://node-0.unmarshal.v2.us.cdn.testnet.cere.network`, + publicKey: "0x685168b78deb42eebf01e38d18c9302f032c50e544d56c1c4f86b13b0a2ad40a", + }, + { + url: `https://node-1.unmarshal.v2.us.cdn.testnet.cere.network`, + publicKey: "0xeeb3683dcd43e9c7f8759b1dce2440d767ae1c51dec05b584d785e24997cb947", + }, + ], + }, + + mainnet: { + ws_provider: "wss://archive.testnet.cere.network/ws", + contract_address: "6So8eqxMyWAxJ4ZZ2wCcJym7Cy6BYkc4V8GZZD9wgdCqWMQB", + cluster: { + 1n: { + param: { replicationFactor: 3 }, + vnodes: [ [0n], [GEN / 3n], [GEN * 2n / 3n] ], + storage_nodes: [1n, 2n, 3n], + }, + }, + storage_node_params: [ + { url: `https://node-0.v2.us.storage.mainnet.cere.network` }, + { url: `https://node-1.v2.us.storage.mainnet.cere.network` }, + { url: `https://node-2.v2.us.storage.mainnet.cere.network` }, + ], + cdn_cluster: { + 0n: { + cdn_nodes: [1n, 2n], + }, + }, + cdn_node_params: [ + { + url: `https://node-0.v2.us.cdn.mainnet.cere.network`, + publicKey: "0x86af4db1e433ad221b6fa3c1a9fc4de694ab59408ca57584e50d8fd420e7b45b", + }, + { + url: `https://node-1.v2.us.cdn.mainnet.cere.network`, + publicKey: "0x9a9fb6c479ef7c8f3af54dc0720f08a73d532815d525aa8d69d965e56512440e", + }, + ], + }, +}; diff --git a/bucket/scripts/init.js b/bucket/scripts/init.js new file mode 100644 index 00000000..281fe009 --- /dev/null +++ b/bucket/scripts/init.js @@ -0,0 +1,129 @@ +import { config } from './config.js'; +import * as fs from 'fs'; + +import { ContractPromise } from '@polkadot/api-contract'; +import { ApiPromise, WsProvider, Keyring } from '@polkadot/api'; +import { cryptoWaitReady, mnemonicGenerate } from "@polkadot/util-crypto"; + +const INIT_ENV = process.env.INIT_ENV; +const SUPERADMIN_MNEMONIC = process.env.SUPERADMIN; +const CERE = 10_000_000_000n; + +const txOptions = { + storageDepositLimit: null, + gasLimit: 100_000_000_000n, +}; + +async function signAndSendPromise(txn, signer) { + return new Promise((res, rej) => { + txn + .signAndSend(signer, ({ events = [], status, blockNumber }) => { + if (status.isInvalid) { + console.log(" Transaction invalid"); + rej("Transaction invalid"); + } else if (status.isReady) { + console.log(" Transaction is ready"); + } else if (status.isBroadcast) { + console.log(" Transaction has been broadcasted"); + } else if (status.isInBlock) { + const blockHash = status.asInBlock.toHex(); + console.log(` Transaction is in block: ${blockHash} of ${blockNumber}`); + } else if (status.isFinalized) { + const blockHash = status.asFinalized.toHex(); + console.log(` Transaction has been included in blockHash ${blockHash} of ${blockNumber}`); + const treasuryDeposit = events.find( + (event) => event.event.toHuman().method === "Deposit" && event.event.toHuman().section === "treasury", + ); + const txFee = treasuryDeposit ? treasuryDeposit.event.toHuman().data.value : undefined; + const txFeeParsed = txFee ? (parseFloat(txFee.replace(" mCERE", "")) / 1000) * 2 : undefined; + + if (events.find(event => event.event.toHuman().method === "ExtrinsicSuccess")) res({ blockHash, txFeeParsed, events }); + else rej("No success found: " + blockHash); + } + }) + .catch((err) => rej(err)); + }); +} + +function createUser() { + const keyring = new Keyring({ type: "sr25519" }); + const mnemonic = mnemonicGenerate(12); + const account = keyring.addFromUri(mnemonic); + + return { + mnemonic: mnemonic, + address: account.address, + addressBase64: Buffer.from(account.publicKey).toString("base64"), + }; +} + +const cfg = config[INIT_ENV]; +if (cfg === undefined) { + console.error("Please provide INIT_ENV as one of ", Object.keys(config)); + process.exit(-1); +} +console.log(cfg); + +await cryptoWaitReady(); +const keyring = new Keyring({ type: "sr25519" }); +const alice = keyring.addFromUri("//Alice"); +const sadmin = keyring.addFromUri(SUPERADMIN_MNEMONIC); +console.log(`Superadmin: ${sadmin.address}`); + +// Contract metadata +const metadata = fs.readFileSync('./metadata.json', 'utf8'); + +// Construct +const wsProvider = new WsProvider(cfg.ws_provider); +const api = await ApiPromise.create({ provider: wsProvider }); +const contract = new ContractPromise(api, metadata, cfg.contract_address); + +console.log("1. adminGrantPermission"); +const res = await signAndSendPromise(await contract.tx.adminGrantPermission(txOptions, sadmin.address, "SuperAdmin"), sadmin); + +console.log("2. accountSetUsdPerCere"); +await signAndSendPromise(await contract.tx.accountSetUsdPerCere(txOptions, 1000n * CERE), sadmin); + +console.log("3. cdnNodeTrustManager"); +await signAndSendPromise(await contract.tx.cdnNodeTrustManager(txOptions, sadmin.address), sadmin); + +console.log("4. nodeTrustManager"); +await signAndSendPromise(await contract.tx.nodeTrustManager(txOptions, sadmin.address), sadmin); + +console.log("5. cdnNodeCreate"); +for (let i = 0; i < cfg.cdn_node_params.length; i++) { + await signAndSendPromise(await contract.tx.cdnNodeCreate(txOptions, JSON.stringify(cfg.cdn_node_params[i])), sadmin); +} + +for (let id in cfg.cdn_cluster) { + const clu = cfg.cdn_cluster[id]; + console.log("6. cdnClusterCreate, cluster: ", id, clu); + await signAndSendPromise(await contract.tx.cdnClusterCreate(txOptions, clu.cdn_nodes), sadmin); +} + +console.log("7. nodeCreate"); +for (let i = 0; i < cfg.storage_node_params.length; i++) { + const param = JSON.stringify(cfg.storage_node_params[i]); + const user = createUser(); + fs.appendFileSync('secrets.txt', `${user.address}: ${user.mnemonic} -- ${INIT_ENV} storage ${i}\n`); + console.log(` node ${i}: address ${user.address}, param ${param}`); + await signAndSendPromise(await contract.tx.nodeCreate(txOptions, 1n * CERE, param, 100000n, "ACTIVE", user.address), sadmin); +} + +for (let id in cfg.cluster) { + const clu = cfg.cluster[id]; + + console.log("8. clusterCreate, cluster: ", id, clu); + await signAndSendPromise(await contract.tx.clusterCreate(txOptions, alice.address, clu.vnodes, clu.storage_nodes, JSON.stringify(clu.param)), sadmin); + + console.log("9. clusterReserveResource, cluster: ", id); + await signAndSendPromise(await contract.tx.clusterReserveResource(txOptions, id, 100000n), sadmin); +} + +// console.log("cdnNodeChangeParams"); +// for (let i = 0; i < cfg.cdn_node_params.length; i++) { +// await signAndSendPromise(await contract.tx.cdnNodeChangeParams(txOptions, i+1, JSON.stringify(cfg.cdn_node_params[i])), sadmin); +// } + +//console.log(res.events.map(event => event.event.toHuman())); +process.exit(0); diff --git a/bucket/scripts/metadata.json b/bucket/scripts/metadata.json new file mode 100644 index 00000000..5233dd85 --- /dev/null +++ b/bucket/scripts/metadata.json @@ -0,0 +1,4959 @@ +{ + "source": { + "hash": "0x17173e6d800d4555fa6b27c1cb7a5bf509796c993c1ed7e1206e8ef27c21fb48", + "language": "ink! 3.4.0", + "compiler": "rustc 1.69.0-nightly" + }, + "contract": { + "name": "ddc_bucket", + "version": "0.5.2", + "authors": [ + "Aurélien Nicolas " + ], + "description": "DDC v2 Smart Contracts -- Orchestrate the network around clusters and buckets", + "license": "Apache-2.0" + }, + "V3": { + "spec": { + "constructors": [ + { + "args": [], + "docs": [ + "Create a new contract.", + "", + "The caller will be admin of the contract." + ], + "label": "new", + "payable": false, + "selector": "0x9bae9d5e" + } + ], + "docs": [], + "events": [ + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": true, + "label": "owner_id", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " A bucket was created. The given account is its first owner and payer of resources." + ], + "label": "BucketCreated" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": true, + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": false, + "label": "resource", + "type": { + "displayName": [ + "Resource" + ], + "type": 9 + } + } + ], + "docs": [ + " Some amount of resources of a cluster were allocated to a bucket." + ], + "label": "BucketAllocated" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": true, + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + } + ], + "docs": [ + " The due costs of a bucket was settled from the bucket payer to the cluster." + ], + "label": "BucketSettlePayment" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": true, + "label": "public_availability", + "type": { + "displayName": [ + "bool" + ], + "type": 3 + } + } + ], + "docs": [ + " The availiablity of the bucket was updated." + ], + "label": "BucketAvailabilityUpdated" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": true, + "label": "manager", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + }, + { + "docs": [], + "indexed": false, + "label": "cluster_params", + "type": { + "displayName": [ + "ClusterParams" + ], + "type": 16 + } + } + ], + "docs": [ + " A new cluster was created." + ], + "label": "ClusterCreated" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": true, + "label": "node_id", + "type": { + "displayName": [ + "NodeId" + ], + "type": 9 + } + } + ], + "docs": [ + " A vnode was re-assigned to new node." + ], + "label": "ClusterNodeReplaced" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": false, + "label": "resource", + "type": { + "displayName": [ + "Resource" + ], + "type": 9 + } + } + ], + "docs": [ + " Some resources were reserved for the cluster from the nodes." + ], + "label": "ClusterReserveResource" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": true, + "label": "provider_id", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " The share of revenues of a cluster for a provider was distributed." + ], + "label": "ClusterDistributeRevenues" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": true, + "label": "manager", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " A new cluster was created." + ], + "label": "CdnClusterCreated" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": true, + "label": "provider_id", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " The respective share of revenues of a CDN cluster for a provider was distributed." + ], + "label": "CdnClusterDistributeRevenues" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "node_id", + "type": { + "displayName": [ + "NodeId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": true, + "label": "provider_id", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + }, + { + "docs": [], + "indexed": false, + "label": "undistributed_payment", + "type": { + "displayName": [ + "Balance" + ], + "type": 12 + } + } + ], + "docs": [ + " A node was created. The given account is its owner and recipient of revenues." + ], + "label": "CdnNodeCreated" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "node_id", + "type": { + "displayName": [ + "NodeId" + ], + "type": 9 + } + }, + { + "docs": [], + "indexed": true, + "label": "provider_id", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + }, + { + "docs": [], + "indexed": false, + "label": "rent_per_month", + "type": { + "displayName": [ + "Balance" + ], + "type": 12 + } + }, + { + "docs": [], + "indexed": false, + "label": "node_params", + "type": { + "displayName": [ + "NodeParams" + ], + "type": 16 + } + } + ], + "docs": [ + " A node was created. The given account is its owner and recipient of revenues." + ], + "label": "NodeCreated" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "account_id", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + }, + { + "docs": [], + "indexed": false, + "label": "value", + "type": { + "displayName": [ + "Balance" + ], + "type": 12 + } + } + ], + "docs": [ + " Tokens were deposited on an account." + ], + "label": "Deposit" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "account_id", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + }, + { + "docs": [], + "indexed": false, + "label": "permission", + "type": { + "displayName": [ + "Permission" + ], + "type": 77 + } + } + ], + "docs": [ + " A permission was granted to the account." + ], + "label": "GrantPermission" + }, + { + "args": [ + { + "docs": [], + "indexed": true, + "label": "account_id", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + }, + { + "docs": [], + "indexed": false, + "label": "permission", + "type": { + "displayName": [ + "Permission" + ], + "type": 77 + } + } + ], + "docs": [ + " A permission was revoked from the account." + ], + "label": "RevokePermission" + } + ], + "messages": [ + { + "args": [ + { + "label": "bucket_params", + "type": { + "displayName": [ + "BucketParams" + ], + "type": 16 + } + }, + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "label": "owner_id", + "type": { + "displayName": [ + "Option" + ], + "type": 43 + } + } + ], + "docs": [ + " Create a new bucket and return its `bucket_id`.", + "", + " The caller will be its first owner and payer of resources.", + "", + " `bucket_params` is configuration used by clients and nodes. See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema)", + "", + " The bucket can be connected to a single cluster (currently). Allocate cluster resources with the function `bucket_alloc_into_cluster`" + ], + "label": "bucket_create", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [ + "BucketId" + ], + "type": 9 + }, + "selector": "0x0aeb2379" + }, + { + "args": [ + { + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + }, + { + "label": "owner_id", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " Change owner of the bucket", + "", + " Provide the account of new owner" + ], + "label": "bucket_change_owner", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0xc7d0c2cd" + }, + { + "args": [ + { + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + }, + { + "label": "resource", + "type": { + "displayName": [ + "Resource" + ], + "type": 9 + } + } + ], + "docs": [ + " Allocate some resources of a cluster to a bucket.", + "", + " The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes)." + ], + "label": "bucket_alloc_into_cluster", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0x4c482d19" + }, + { + "args": [ + { + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + } + ], + "docs": [ + " Settle the due costs of a bucket from its payer account to the cluster account." + ], + "label": "bucket_settle_payment", + "mutates": true, + "payable": false, + "returnType": null, + "selector": "0x15974555" + }, + { + "args": [ + { + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + }, + { + "label": "params", + "type": { + "displayName": [ + "BucketParams" + ], + "type": 16 + } + } + ], + "docs": [ + " Change the `bucket_params`, which is configuration used by clients and nodes.", + "", + " See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" + ], + "label": "bucket_change_params", + "mutates": true, + "payable": true, + "returnType": null, + "selector": "0x9f2d075b" + }, + { + "args": [ + { + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + } + ], + "docs": [ + " Get the current status of a bucket." + ], + "label": "bucket_get", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 45 + }, + "selector": "0x3802cb77" + }, + { + "args": [ + { + "label": "offset", + "type": { + "displayName": [ + "u32" + ], + "type": 9 + } + }, + { + "label": "limit", + "type": { + "displayName": [ + "u32" + ], + "type": 9 + } + }, + { + "label": "filter_owner_id", + "type": { + "displayName": [ + "Option" + ], + "type": 43 + } + } + ], + "docs": [ + " Iterate through all buckets.", + "", + " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", + " The optimal `limit` depends on the size of params.", + "", + " The results can be filtered by owner. Note that paging must still be completed fully." + ], + "label": "bucket_list", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [], + "type": 49 + }, + "selector": "0x417ab584" + }, + { + "args": [ + { + "label": "owner_id", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " Iterate through all buckets and return only those owned by owner", + "", + " This method returns bucket struct, not the status" + ], + "label": "bucket_list_for_account", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Vec" + ], + "type": 6 + }, + "selector": "0xc434cf57" + }, + { + "args": [ + { + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + }, + { + "label": "public_availability", + "type": { + "displayName": [ + "bool" + ], + "type": 3 + } + } + ], + "docs": [ + " Set availiablity of the bucket" + ], + "label": "bucket_set_availability", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0x053eb3ce" + }, + { + "args": [ + { + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + }, + { + "label": "new_resource_cap", + "type": { + "displayName": [ + "Resource" + ], + "type": 9 + } + } + ], + "docs": [ + " Set max resource cap to be charged by CDN for public bucket" + ], + "label": "bucket_set_resource_cap", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0x85010c6d" + }, + { + "args": [ + { + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + } + ], + "docs": [ + " Set permission for the reader of the bucket" + ], + "label": "get_bucket_writers", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Vec" + ], + "type": 14 + }, + "selector": "0x499cd4b7" + }, + { + "args": [ + { + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + }, + { + "label": "writer", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " Set permission for the writer of the bucket" + ], + "label": "bucket_set_writer_perm", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0xea2e477a" + }, + { + "args": [ + { + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + }, + { + "label": "writer", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " Revoke permission for the writer of the bucket" + ], + "label": "bucket_revoke_writer_perm", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0x2b3d8dd1" + }, + { + "args": [ + { + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + } + ], + "docs": [ + " Set permission for the reader of the bucket" + ], + "label": "get_bucket_readers", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Vec" + ], + "type": 14 + }, + "selector": "0xb9a7cc1c" + }, + { + "args": [ + { + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + }, + { + "label": "reader", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " Set permission for the reader of the bucket" + ], + "label": "bucket_set_reader_perm", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0xfc0e94ea" + }, + { + "args": [ + { + "label": "bucket_id", + "type": { + "displayName": [ + "BucketId" + ], + "type": 9 + } + }, + { + "label": "writer", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " Revoke permission for the reader of the bucket" + ], + "label": "bucket_revoke_reader_perm", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0xe9bfed5a" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "label": "node_ids", + "type": { + "displayName": [ + "Vec" + ], + "type": 20 + } + }, + { + "label": "v_nodes", + "type": { + "displayName": [ + "Vec" + ], + "type": 21 + } + } + ], + "docs": [ + " Removes a node to an existing cluster", + "", + " The caller will be its first manager." + ], + "label": "cluster_remove_node", + "mutates": true, + "payable": true, + "returnType": null, + "selector": "0x793e0778" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "label": "node_ids", + "type": { + "displayName": [ + "Vec" + ], + "type": 20 + } + }, + { + "label": "v_nodes", + "type": { + "displayName": [ + "Vec" + ], + "type": 21 + } + } + ], + "docs": [ + " Adds node to an existing cluster", + "", + " The caller will be its first manager." + ], + "label": "cluster_add_node", + "mutates": true, + "payable": true, + "returnType": null, + "selector": "0xf7496bdc" + }, + { + "args": [ + { + "label": "_unused", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + }, + { + "label": "v_nodes", + "type": { + "displayName": [ + "Vec" + ], + "type": 21 + } + }, + { + "label": "node_ids", + "type": { + "displayName": [ + "Vec" + ], + "type": 20 + } + }, + { + "label": "cluster_params", + "type": { + "displayName": [ + "ClusterParams" + ], + "type": 16 + } + } + ], + "docs": [ + " Create a new cluster and return its `cluster_id`.", + "", + " The caller will be its first manager.", + "", + " The cluster is split in a number of vnodes. The vnodes are assigned to the given physical nodes in a round-robin. Only nodes of providers that trust the cluster manager can be used (see `node_trust_manager`). The assignment can be changed with the function `cluster_replace_node`.", + "", + " `cluster_params` is configuration used by clients and nodes. In particular, this describes the semantics of vnodes. See the [data structure of ClusterParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" + ], + "label": "cluster_create", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [ + "ClusterId" + ], + "type": 9 + }, + "selector": "0x4c0f21f6" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "label": "amount", + "type": { + "displayName": [ + "Resource" + ], + "type": 9 + } + } + ], + "docs": [ + " As manager, reserve more resources for the cluster from the free capacity of nodes.", + "", + " The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes)." + ], + "label": "cluster_reserve_resource", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0xb5e38125" + }, + { + "args": [ + { + "label": "node_id", + "type": { + "displayName": [ + "NodeId" + ], + "type": 9 + } + }, + { + "label": "new_tag", + "type": { + "displayName": [ + "NodeTag" + ], + "type": 31 + } + } + ], + "docs": [ + " As manager, change a node tag" + ], + "label": "cluster_change_node_tag", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0x9640d48e" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "label": "v_nodes", + "type": { + "displayName": [ + "Vec" + ], + "type": 22 + } + }, + { + "label": "new_node_id", + "type": { + "displayName": [ + "NodeId" + ], + "type": 9 + } + } + ], + "docs": [ + " As manager, re-assign a vnode to another physical node.", + "", + " The cluster manager can only use nodes of providers that trust him (see `node_trust_manager`), or any nodes if he is also SuperAdmin." + ], + "label": "cluster_replace_node", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0x48194ab1" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + } + ], + "docs": [ + " Trigger the distribution of revenues from the cluster to the providers." + ], + "label": "cluster_distribute_revenues", + "mutates": true, + "payable": false, + "returnType": null, + "selector": "0xe71e66fc" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "label": "params", + "type": { + "displayName": [ + "ClusterParams" + ], + "type": 16 + } + } + ], + "docs": [ + " Change the `cluster_params`, which is configuration used by clients and nodes.", + "", + " See the [data structure of ClusterParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" + ], + "label": "cluster_change_params", + "mutates": true, + "payable": true, + "returnType": null, + "selector": "0x1207912c" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + } + ], + "docs": [ + " Get the current status of a cluster." + ], + "label": "cluster_get", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 51 + }, + "selector": "0xe75411f5" + }, + { + "args": [ + { + "label": "offset", + "type": { + "displayName": [ + "u32" + ], + "type": 9 + } + }, + { + "label": "limit", + "type": { + "displayName": [ + "u32" + ], + "type": 9 + } + }, + { + "label": "filter_manager_id", + "type": { + "displayName": [ + "Option" + ], + "type": 43 + } + } + ], + "docs": [ + " Iterate through all clusters.", + "", + " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", + " The optimal `limit` depends on the size of params.", + "", + " The results can be filtered by manager. Note that paging must still be completed fully." + ], + "label": "cluster_list", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [], + "type": 53 + }, + "selector": "0xd9db9d44" + }, + { + "args": [ + { + "label": "cdn_node_ids", + "type": { + "displayName": [ + "Vec" + ], + "type": 20 + } + } + ], + "docs": [ + " Create a new cluster and return its `cluster_id`.", + "", + " The caller will be its first manager.", + "", + " The CDN node ids are provided, which will form a cluster." + ], + "label": "cdn_cluster_create", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [ + "ClusterId" + ], + "type": 9 + }, + "selector": "0x4344cd7e" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "label": "usd_per_gb", + "type": { + "displayName": [ + "Balance" + ], + "type": 12 + } + } + ], + "docs": [ + " Set rate for streaming (price per gb)" + ], + "label": "cdn_set_rate", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0x7578922a" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + } + ], + "docs": [ + " Get rate for streaming (price per gb)" + ], + "label": "cdn_get_rate", + "mutates": false, + "payable": true, + "returnType": { + "displayName": [ + "Balance" + ], + "type": 12 + }, + "selector": "0xa1e3ea8a" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + }, + { + "label": "aggregates_accounts", + "type": { + "displayName": [ + "Vec" + ], + "type": 55 + } + }, + { + "label": "aggregates_nodes", + "type": { + "displayName": [ + "Vec" + ], + "type": 57 + } + }, + { + "label": "aggregates_buckets", + "type": { + "displayName": [ + "Vec" + ], + "type": 59 + } + }, + { + "label": "era", + "type": { + "displayName": [ + "u64" + ], + "type": 23 + } + } + ], + "docs": [ + " As validator, charge payments from users and allocate undistributed payments to CDN nodes.", + "", + " As a result CDN cluster revenue increases, which can be distributed between CDN node providers via method cdn_cluster_distribute_revenues." + ], + "label": "cdn_cluster_put_revenue", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0x7219be3f" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + } + ], + "docs": [ + " Trigger the distribution of revenues from the cluster to the CDN node providers.", + "", + " Anyone can call this method.", + "", + " Undistributed payments will be trasnferred, CDN cluster revenue will decrease." + ], + "label": "cdn_cluster_distribute_revenues", + "mutates": true, + "payable": false, + "returnType": null, + "selector": "0xfa8d570d" + }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 9 + } + } + ], + "docs": [ + " Get the current status of a cluster." + ], + "label": "cdn_cluster_get", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 61 + }, + "selector": "0x4b22fbf1" + }, + { + "args": [ + { + "label": "offset", + "type": { + "displayName": [ + "u32" + ], + "type": 9 + } + }, + { + "label": "limit", + "type": { + "displayName": [ + "u32" + ], + "type": 9 + } + }, + { + "label": "filter_manager_id", + "type": { + "displayName": [ + "Option" + ], + "type": 43 + } + } + ], + "docs": [ + " Iterate through all clusters.", + "", + " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", + " The optimal `limit` depends on the size of params.", + "", + " The results can be filtered by manager. Note that paging must still be completed fully." + ], + "label": "cdn_cluster_list", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [], + "type": 63 + }, + "selector": "0xb242a64f" + }, + { + "args": [ + { + "label": "cdn_owner", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + }, + { + "label": "node_id", + "type": { + "displayName": [ + "NodeId" + ], + "type": 9 + } + }, + { + "label": "commit", + "type": { + "displayName": [ + "Commit" + ], + "type": 37 + } + } + ], + "docs": [ + " CDN node operator sets the commit for current era." + ], + "label": "set_commit", + "mutates": true, + "payable": false, + "returnType": null, + "selector": "0xe445e1fd" + }, + { + "args": [ + { + "label": "cdn_owner", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " Return the last commit submitted by CDN node operator" + ], + "label": "get_commit", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Vec" + ], + "type": 35 + }, + "selector": "0x5329f551" + }, + { + "args": [ + { + "label": "node", + "type": { + "displayName": [ + "NodeId" + ], + "type": 9 + } + } + ], + "docs": [ + " Return last era validated per CDN node" + ], + "label": "get_validated_commit", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "EraAndTimestamp" + ], + "type": 40 + }, + "selector": "0x7d497bc1" + }, + { + "args": [ + { + "label": "era_config", + "type": { + "displayName": [ + "EraConfig" + ], + "type": 65 + } + } + ], + "docs": [ + " Set the new configs for era" + ], + "label": "set_era", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0x49a5b8f7" + }, + { + "args": [], + "docs": [ + " Return current status of an era" + ], + "label": "get_era", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "EraStatus" + ], + "type": 66 + }, + "selector": "0x617f696b" + }, + { + "args": [], + "docs": [ + " Return current era settings" + ], + "label": "get_era_settings", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "EraConfig" + ], + "type": 65 + }, + "selector": "0x84b61468" + }, + { + "args": [ + { + "label": "manager", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " As node provider, authorize a cluster manager to use his nodes." + ], + "label": "cdn_node_trust_manager", + "mutates": true, + "payable": true, + "returnType": null, + "selector": "0x372daa96" + }, + { + "args": [ + { + "label": "manager", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " As node provider, revoke the authorization of a cluster manager to use his nodes." + ], + "label": "cdn_node_distrust_manager", + "mutates": true, + "payable": false, + "returnType": null, + "selector": "0xf67f5438" + }, + { + "args": [ + { + "label": "node_params", + "type": { + "displayName": [ + "Params" + ], + "type": 16 + } + } + ], + "docs": [ + " Create a new node and return its `node_id`.", + "", + " The caller will be its owner.", + "", + " `node_params` is configuration used by clients and nodes. In particular, this contains the URL to the service. See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" + ], + "label": "cdn_node_create", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [ + "NodeId" + ], + "type": 9 + }, + "selector": "0xe8aa4ade" + }, + { + "args": [ + { + "label": "node_id", + "type": { + "displayName": [ + "NodeId" + ], + "type": 9 + } + }, + { + "label": "params", + "type": { + "displayName": [ + "NodeParams" + ], + "type": 16 + } + } + ], + "docs": [ + " Change the `node_params`, which is configuration used by clients and nodes.", + "", + " See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" + ], + "label": "cdn_node_change_params", + "mutates": true, + "payable": true, + "returnType": null, + "selector": "0xf52c20f5" + }, + { + "args": [ + { + "label": "node_id", + "type": { + "displayName": [ + "NodeId" + ], + "type": 9 + } + } + ], + "docs": [ + " Get the current state of the cdn node" + ], + "label": "cdn_node_get", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 68 + }, + "selector": "0xf9a5a813" + }, + { + "args": [ + { + "label": "offset", + "type": { + "displayName": [ + "u32" + ], + "type": 9 + } + }, + { + "label": "limit", + "type": { + "displayName": [ + "u32" + ], + "type": 9 + } + }, + { + "label": "filter_provider_id", + "type": { + "displayName": [ + "Option" + ], + "type": 43 + } + } + ], + "docs": [ + " Iterate through all nodes.", + "", + " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", + " The optimal `limit` depends on the size of params.", + "", + " The results can be filtered by owner. Note that paging must still be completed fully." + ], + "label": "cdn_node_list", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [], + "type": 70 + }, + "selector": "0xf8589aae" + }, + { + "args": [ + { + "label": "manager", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " As node provider, authorize a cluster manager to use his nodes." + ], + "label": "node_trust_manager", + "mutates": true, + "payable": true, + "returnType": null, + "selector": "0x6fd54a01" + }, + { + "args": [ + { + "label": "manager", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " As node provider, revoke the authorization of a cluster manager to use his nodes." + ], + "label": "node_distrust_manager", + "mutates": true, + "payable": false, + "returnType": null, + "selector": "0x40912279" + }, + { + "args": [ + { + "label": "rent_per_month", + "type": { + "displayName": [ + "Balance" + ], + "type": 12 + } + }, + { + "label": "node_params", + "type": { + "displayName": [ + "NodeParams" + ], + "type": 16 + } + }, + { + "label": "capacity", + "type": { + "displayName": [ + "Resource" + ], + "type": 9 + } + }, + { + "label": "node_tag", + "type": { + "displayName": [ + "NodeTag" + ], + "type": 31 + } + }, + { + "label": "pubkey", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " Create a new node and return its `node_id`.", + "", + " The caller will be its owner.", + "", + " `node_params` is configuration used by clients and nodes. In particular, this contains the URL to the service. See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" + ], + "label": "node_create", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [ + "NodeId" + ], + "type": 9 + }, + "selector": "0xb77ac1bb" + }, + { + "args": [ + { + "label": "node_id", + "type": { + "displayName": [ + "NodeId" + ], + "type": 9 + } + }, + { + "label": "params", + "type": { + "displayName": [ + "NodeParams" + ], + "type": 16 + } + } + ], + "docs": [ + " Change the `node_params`, which is configuration used by clients and nodes.", + "", + " See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" + ], + "label": "node_change_params", + "mutates": true, + "payable": true, + "returnType": null, + "selector": "0x258ccb2a" + }, + { + "args": [ + { + "label": "node_id", + "type": { + "displayName": [ + "NodeId" + ], + "type": 9 + } + } + ], + "docs": [ + " Get the current status of a node." + ], + "label": "node_get", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 72 + }, + "selector": "0x847f3997" + }, + { + "args": [ + { + "label": "pubkey", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " Get the current status of a node by a public key." + ], + "label": "node_get_by_pubkey", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 72 + }, + "selector": "0x7f6c82d4" + }, + { + "args": [ + { + "label": "offset", + "type": { + "displayName": [ + "u32" + ], + "type": 9 + } + }, + { + "label": "limit", + "type": { + "displayName": [ + "u32" + ], + "type": 9 + } + }, + { + "label": "filter_provider_id", + "type": { + "displayName": [ + "Option" + ], + "type": 43 + } + } + ], + "docs": [ + " Iterate through all nodes.", + "", + " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", + " The optimal `limit` depends on the size of params.", + "", + " The results can be filtered by owner. Note that paging must still be completed fully." + ], + "label": "node_list", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [], + "type": 74 + }, + "selector": "0x423286d6" + }, + { + "args": [], + "docs": [ + " Get the Fee Percentage Basis Points that will be charged by the protocol" + ], + "label": "get_fee_bp", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "u32" + ], + "type": 9 + }, + "selector": "0x0d5daf5f" + }, + { + "args": [ + { + "label": "fee_bp", + "type": { + "displayName": [ + "u32" + ], + "type": 9 + } + } + ], + "docs": [ + " Return the last commit submitted by CDN node operator" + ], + "label": "set_fee_bp", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0xc5e3e2ca" + }, + { + "args": [], + "docs": [ + " Return fees accumulated by the protocol" + ], + "label": "get_protocol_revenues", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Cash" + ], + "type": 19 + }, + "selector": "0x07c63885" + }, + { + "args": [ + { + "label": "amount", + "type": { + "displayName": [ + "u128" + ], + "type": 12 + } + } + ], + "docs": [ + " Pay the revenues accumulated by the protocol" + ], + "label": "protocol_withdraw_revenues", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0x85c6fa6d" + }, + { + "args": [], + "docs": [ + " As user, deposit tokens on the account of the caller from the transaction value. This deposit", + " can be used to pay for the services to buckets of the account." + ], + "label": "account_deposit", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0xc311af62" + }, + { + "args": [ + { + "label": "bond_amount", + "type": { + "displayName": [ + "Balance" + ], + "type": 12 + } + } + ], + "docs": [ + " As user, bond some amount of tokens from the withdrawable balance. These funds will be used to pay for CDN node service." + ], + "label": "account_bond", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0xe9fad0bf" + }, + { + "args": [ + { + "label": "amount_to_unbond", + "type": { + "displayName": [ + "Cash" + ], + "type": 19 + } + } + ], + "docs": [ + " As user, unbond a specified amount of tokens. The tokens will be locked for some time, as defined by contract owner." + ], + "label": "account_unbond", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0xf7ea2c67" + }, + { + "args": [], + "docs": [ + " As user, move the unbonded tokens back to withdrawable balance state.", + "", + " This can be triggered after unbonded_timestamp" + ], + "label": "account_withdraw_unbonded", + "mutates": true, + "payable": true, + "returnType": { + "displayName": [], + "type": 44 + }, + "selector": "0x98173716" + }, + { + "args": [ + { + "label": "account_id", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + } + ], + "docs": [ + " Get the current status of an account." + ], + "label": "account_get", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 76 + }, + "selector": "0x1d4220fa" + }, + { + "args": [], + "docs": [ + " Get the current conversion rate between the native currency and an external currency (USD)." + ], + "label": "account_get_usd_per_cere", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "Balance" + ], + "type": 12 + }, + "selector": "0xe4a4652a" + }, + { + "args": [ + { + "label": "usd_per_cere", + "type": { + "displayName": [ + "Balance" + ], + "type": 12 + } + } + ], + "docs": [ + " As price oracle, set the current conversion rate between the native currency and an external currency (USD).", + "", + " This requires the permission SetExchangeRate or SuperAdmin." + ], + "label": "account_set_usd_per_cere", + "mutates": true, + "payable": false, + "returnType": null, + "selector": "0x48d45ee8" + }, + { + "args": [ + { + "label": "grantee", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + }, + { + "label": "permission", + "type": { + "displayName": [ + "Permission" + ], + "type": 77 + } + } + ], + "docs": [ + " Check whether the given account has the given permission currently,", + " or the SuperAdmin permission." + ], + "label": "has_permission", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "bool" + ], + "type": 3 + }, + "selector": "0xe0942492" + }, + { + "args": [ + { + "label": "grantee", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + }, + { + "label": "permission", + "type": { + "displayName": [ + "Permission" + ], + "type": 77 + } + } + ], + "docs": [ + " As SuperAdmin, grant any permission to any account." + ], + "label": "admin_grant_permission", + "mutates": true, + "payable": true, + "returnType": null, + "selector": "0xbe41ea55" + }, + { + "args": [ + { + "label": "grantee", + "type": { + "displayName": [ + "AccountId" + ], + "type": 8 + } + }, + { + "label": "permission", + "type": { + "displayName": [ + "Permission" + ], + "type": 77 + } + } + ], + "docs": [ + " As SuperAdmin, revoke any permission to any account." + ], + "label": "admin_revoke_permission", + "mutates": true, + "payable": false, + "returnType": null, + "selector": "0x6b150666" + }, + { + "args": [ + { + "label": "amount", + "type": { + "displayName": [ + "Balance" + ], + "type": 12 + } + } + ], + "docs": [ + " As SuperAdmin, withdraw the funds held in custody in this contract.", + "", + " This is a temporary measure to allow migrating the funds to a new version of the contract." + ], + "label": "admin_withdraw", + "mutates": true, + "payable": false, + "returnType": null, + "selector": "0x2f6e0868" + }, + { + "args": [ + { + "label": "config", + "type": { + "displayName": [ + "FeeConfig" + ], + "type": 78 + } + } + ], + "docs": [ + " As SuperAdmin, set the network and cluster fee configuration." + ], + "label": "admin_set_fee_config", + "mutates": true, + "payable": false, + "returnType": null, + "selector": "0x00d441e7" + }, + { + "args": [], + "docs": [ + " Get all Account IDs stored in the SC" + ], + "label": "get_accounts", + "mutates": false, + "payable": true, + "returnType": { + "displayName": [ + "Vec" + ], + "type": 14 + }, + "selector": "0xef03ead7" + } + ] + }, + "storage": { + "struct": { + "fields": [ + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0000000000000000000000000000000000000000000000000000000000000000", + "ty": 0 + } + }, + "name": null + } + ] + } + }, + "name": "perms" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0100000000000000000000000000000000000000000000000000000000000000", + "ty": 6 + } + }, + "name": null + } + ] + } + }, + "name": "buckets" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0200000000000000000000000000000000000000000000000000000000000000", + "ty": 13 + } + }, + "name": "writers" + }, + { + "layout": { + "cell": { + "key": "0x0300000000000000000000000000000000000000000000000000000000000000", + "ty": 13 + } + }, + "name": "readers" + } + ] + } + }, + "name": "buckets_perms" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0400000000000000000000000000000000000000000000000000000000000000", + "ty": 15 + } + }, + "name": null + } + ] + } + }, + "name": "bucket_params" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0500000000000000000000000000000000000000000000000000000000000000", + "ty": 17 + } + }, + "name": null + } + ] + } + }, + "name": "clusters" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0600000000000000000000000000000000000000000000000000000000000000", + "ty": 24 + } + }, + "name": null + } + ] + } + }, + "name": "cdn_clusters" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0700000000000000000000000000000000000000000000000000000000000000", + "ty": 15 + } + }, + "name": null + } + ] + } + }, + "name": "cluster_params" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0800000000000000000000000000000000000000000000000000000000000000", + "ty": 26 + } + }, + "name": null + } + ] + } + }, + "name": "cdn_nodes" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0900000000000000000000000000000000000000000000000000000000000000", + "ty": 15 + } + }, + "name": null + } + ] + } + }, + "name": "cdn_node_params" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0a00000000000000000000000000000000000000000000000000000000000000", + "ty": 28 + } + }, + "name": "account_node" + }, + { + "layout": { + "cell": { + "key": "0x0b00000000000000000000000000000000000000000000000000000000000000", + "ty": 29 + } + }, + "name": "nodes" + } + ] + } + }, + "name": "nodes" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0c00000000000000000000000000000000000000000000000000000000000000", + "ty": 15 + } + }, + "name": null + } + ] + } + }, + "name": "node_params" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0d00000000000000000000000000000000000000000000000000000000000000", + "ty": 32 + } + }, + "name": null + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x0e00000000000000000000000000000000000000000000000000000000000000", + "ty": 12 + } + }, + "name": null + } + ] + } + }, + "name": null + }, + { + "layout": { + "cell": { + "key": "0x0f00000000000000000000000000000000000000000000000000000000000000", + "ty": 14 + } + }, + "name": null + } + ] + } + }, + "name": "accounts" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x1000000000000000000000000000000000000000000000000000000000000000", + "ty": 12 + } + }, + "name": "network_fee_bp" + }, + { + "layout": { + "cell": { + "key": "0x1100000000000000000000000000000000000000000000000000000000000000", + "ty": 8 + } + }, + "name": "network_fee_destination" + }, + { + "layout": { + "cell": { + "key": "0x1200000000000000000000000000000000000000000000000000000000000000", + "ty": 12 + } + }, + "name": "cluster_management_fee_bp" + } + ] + } + }, + "name": null + } + ] + } + }, + "name": "network_fee" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x1300000000000000000000000000000000000000000000000000000000000000", + "ty": 8 + } + }, + "name": "operator_id" + }, + { + "layout": { + "cell": { + "key": "0x1400000000000000000000000000000000000000000000000000000000000000", + "ty": 34 + } + }, + "name": "commits" + }, + { + "layout": { + "cell": { + "key": "0x1500000000000000000000000000000000000000000000000000000000000000", + "ty": 39 + } + }, + "name": "validated_commits" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x1600000000000000000000000000000000000000000000000000000000000000", + "ty": 23 + } + }, + "name": "start" + }, + { + "layout": { + "cell": { + "key": "0x1700000000000000000000000000000000000000000000000000000000000000", + "ty": 23 + } + }, + "name": "interval" + }, + { + "layout": { + "cell": { + "key": "0x1800000000000000000000000000000000000000000000000000000000000000", + "ty": 23 + } + }, + "name": "commit_duration" + }, + { + "layout": { + "cell": { + "key": "0x1900000000000000000000000000000000000000000000000000000000000000", + "ty": 23 + } + }, + "name": "validation_duration" + } + ] + } + }, + "name": "era_settings" + } + ] + } + }, + "name": "committer_store" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x1a00000000000000000000000000000000000000000000000000000000000000", + "ty": 8 + } + }, + "name": "admin" + }, + { + "layout": { + "cell": { + "key": "0x1b00000000000000000000000000000000000000000000000000000000000000", + "ty": 9 + } + }, + "name": "fee_bp" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x1c00000000000000000000000000000000000000000000000000000000000000", + "ty": 12 + } + }, + "name": null + } + ] + } + }, + "name": "revenues" + } + ] + } + }, + "name": "protocol_store" + }, + { + "layout": { + "struct": { + "fields": [ + { + "layout": { + "cell": { + "key": "0x1d00000000000000000000000000000000000000000000000000000000000000", + "ty": 41 + } + }, + "name": null + } + ] + } + }, + "name": "topology_store" + } + ] + } + }, + "types": [ + { + "id": 0, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "offset_key", + "type": 4, + "typeName": "Key" + } + ] + } + }, + "params": [ + { + "name": "K", + "type": 1 + }, + { + "name": "V", + "type": 3 + } + ], + "path": [ + "ink_storage", + "lazy", + "mapping", + "Mapping" + ] + } + }, + { + "id": 1, + "type": { + "def": { + "sequence": { + "type": 2 + } + } + } + }, + { + "id": 2, + "type": { + "def": { + "primitive": "u8" + } + } + }, + { + "id": 3, + "type": { + "def": { + "primitive": "bool" + } + } + }, + { + "id": 4, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 5, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_primitives", + "Key" + ] + } + }, + { + "id": 5, + "type": { + "def": { + "array": { + "len": 32, + "type": 2 + } + } + } + }, + { + "id": 6, + "type": { + "def": { + "sequence": { + "type": 7 + } + } + } + }, + { + "id": 7, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "owner_id", + "type": 8, + "typeName": "AccountId" + }, + { + "name": "cluster_id", + "type": 9, + "typeName": "ClusterId" + }, + { + "name": "flow", + "type": 10, + "typeName": "Flow" + }, + { + "name": "resource_reserved", + "type": 9, + "typeName": "Resource" + }, + { + "name": "public_availability", + "type": 3, + "typeName": "bool" + }, + { + "name": "resource_consumption_cap", + "type": 9, + "typeName": "Resource" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "bucket", + "entity", + "Bucket" + ] + } + }, + { + "id": 8, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 5, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_env", + "types", + "AccountId" + ] + } + }, + { + "id": 9, + "type": { + "def": { + "primitive": "u32" + } + } + }, + { + "id": 10, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "from", + "type": 8, + "typeName": "AccountId" + }, + { + "name": "schedule", + "type": 11, + "typeName": "Schedule" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "flow", + "Flow" + ] + } + }, + { + "id": 11, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "rate", + "type": 12, + "typeName": "Balance" + }, + { + "name": "offset", + "type": 12, + "typeName": "Balance" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "schedule", + "Schedule" + ] + } + }, + { + "id": 12, + "type": { + "def": { + "primitive": "u128" + } + } + }, + { + "id": 13, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "offset_key", + "type": 4, + "typeName": "Key" + } + ] + } + }, + "params": [ + { + "name": "K", + "type": 9 + }, + { + "name": "V", + "type": 14 + } + ], + "path": [ + "ink_storage", + "lazy", + "mapping", + "Mapping" + ] + } + }, + { + "id": 14, + "type": { + "def": { + "sequence": { + "type": 8 + } + } + } + }, + { + "id": 15, + "type": { + "def": { + "sequence": { + "type": 16 + } + } + } + }, + { + "id": 16, + "type": { + "def": { + "primitive": "str" + } + } + }, + { + "id": 17, + "type": { + "def": { + "sequence": { + "type": 18 + } + } + } + }, + { + "id": 18, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "manager_id", + "type": 8, + "typeName": "AccountId" + }, + { + "name": "resource_per_vnode", + "type": 9, + "typeName": "Resource" + }, + { + "name": "resource_used", + "type": 9, + "typeName": "Resource" + }, + { + "name": "revenues", + "type": 19, + "typeName": "Cash" + }, + { + "name": "node_ids", + "type": 20, + "typeName": "Vec" + }, + { + "name": "v_nodes", + "type": 21, + "typeName": "Vec>" + }, + { + "name": "total_rent", + "type": 12, + "typeName": "Balance" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "cluster", + "entity", + "Cluster" + ] + } + }, + { + "id": 19, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "value", + "type": 12, + "typeName": "Balance" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "cash", + "Cash" + ] + } + }, + { + "id": 20, + "type": { + "def": { + "sequence": { + "type": 9 + } + } + } + }, + { + "id": 21, + "type": { + "def": { + "sequence": { + "type": 22 + } + } + } + }, + { + "id": 22, + "type": { + "def": { + "sequence": { + "type": 23 + } + } + } + }, + { + "id": 23, + "type": { + "def": { + "primitive": "u64" + } + } + }, + { + "id": 24, + "type": { + "def": { + "sequence": { + "type": 25 + } + } + } + }, + { + "id": 25, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "manager_id", + "type": 8, + "typeName": "AccountId" + }, + { + "name": "cdn_nodes", + "type": 20, + "typeName": "Vec" + }, + { + "name": "resources_used", + "type": 9, + "typeName": "Resource" + }, + { + "name": "revenues", + "type": 19, + "typeName": "Cash" + }, + { + "name": "usd_per_gb", + "type": 12, + "typeName": "Balance" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "cdn_cluster", + "entity", + "CdnCluster" + ] + } + }, + { + "id": 26, + "type": { + "def": { + "sequence": { + "type": 27 + } + } + } + }, + { + "id": 27, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "provider_id", + "type": 8, + "typeName": "ProviderId" + }, + { + "name": "undistributed_payment", + "type": 12, + "typeName": "Balance" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "cdn_node", + "entity", + "CdnNode" + ] + } + }, + { + "id": 28, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "offset_key", + "type": 4, + "typeName": "Key" + } + ] + } + }, + "params": [ + { + "name": "K", + "type": 8 + }, + { + "name": "V", + "type": 9 + } + ], + "path": [ + "ink_storage", + "lazy", + "mapping", + "Mapping" + ] + } + }, + { + "id": 29, + "type": { + "def": { + "sequence": { + "type": 30 + } + } + } + }, + { + "id": 30, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "provider_id", + "type": 8, + "typeName": "ProviderId" + }, + { + "name": "rent_per_month", + "type": 12, + "typeName": "Balance" + }, + { + "name": "free_resource", + "type": 9, + "typeName": "Resource" + }, + { + "name": "node_tag", + "type": 31, + "typeName": "NodeTag" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "node", + "entity", + "Node" + ] + } + }, + { + "id": 31, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 0, + "name": "UNKNOWN" + }, + { + "index": 1, + "name": "ACTIVE" + }, + { + "index": 2, + "name": "ADDING" + }, + { + "index": 3, + "name": "DELETING" + }, + { + "index": 4, + "name": "OFFLINE" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "node", + "entity", + "NodeTag" + ] + } + }, + { + "id": 32, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "offset_key", + "type": 4, + "typeName": "Key" + } + ] + } + }, + "params": [ + { + "name": "K", + "type": 8 + }, + { + "name": "V", + "type": 33 + } + ], + "path": [ + "ink_storage", + "lazy", + "mapping", + "Mapping" + ] + } + }, + { + "id": 33, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "deposit", + "type": 19, + "typeName": "Cash" + }, + { + "name": "bonded", + "type": 19, + "typeName": "Cash" + }, + { + "name": "negative", + "type": 19, + "typeName": "Cash" + }, + { + "name": "unbonded_amount", + "type": 19, + "typeName": "Cash" + }, + { + "name": "unbonded_timestamp", + "type": 23, + "typeName": "u64" + }, + { + "name": "payable_schedule", + "type": 11, + "typeName": "Schedule" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "account", + "entity", + "Account" + ] + } + }, + { + "id": 34, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "offset_key", + "type": 4, + "typeName": "Key" + } + ] + } + }, + "params": [ + { + "name": "K", + "type": 8 + }, + { + "name": "V", + "type": 35 + } + ], + "path": [ + "ink_storage", + "lazy", + "mapping", + "Mapping" + ] + } + }, + { + "id": 35, + "type": { + "def": { + "sequence": { + "type": 36 + } + } + } + }, + { + "id": 36, + "type": { + "def": { + "tuple": [ + 9, + 37 + ] + } + } + }, + { + "id": 37, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "hash", + "type": 38, + "typeName": "Hash" + }, + { + "name": "total_logs", + "type": 12, + "typeName": "u128" + }, + { + "name": "from_timestamp", + "type": 23, + "typeName": "u64" + }, + { + "name": "to_timestamp", + "type": 23, + "typeName": "u64" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "committer", + "store", + "Commit" + ] + } + }, + { + "id": 38, + "type": { + "def": { + "composite": { + "fields": [ + { + "type": 5, + "typeName": "[u8; 32]" + } + ] + } + }, + "path": [ + "ink_env", + "types", + "Hash" + ] + } + }, + { + "id": 39, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "offset_key", + "type": 4, + "typeName": "Key" + } + ] + } + }, + "params": [ + { + "name": "K", + "type": 9 + }, + { + "name": "V", + "type": 40 + } + ], + "path": [ + "ink_storage", + "lazy", + "mapping", + "Mapping" + ] + } + }, + { + "id": 40, + "type": { + "def": { + "tuple": [ + 23, + 23 + ] + } + } + }, + { + "id": 41, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "offset_key", + "type": 4, + "typeName": "Key" + } + ] + } + }, + "params": [ + { + "name": "K", + "type": 42 + }, + { + "name": "V", + "type": 9 + } + ], + "path": [ + "ink_storage", + "lazy", + "mapping", + "Mapping" + ] + } + }, + { + "id": 42, + "type": { + "def": { + "tuple": [ + 9, + 23 + ] + } + } + }, + { + "id": 43, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 0, + "name": "None" + }, + { + "fields": [ + { + "type": 8 + } + ], + "index": 1, + "name": "Some" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 8 + } + ], + "path": [ + "Option" + ] + } + }, + { + "id": 44, + "type": { + "def": { + "tuple": [] + } + } + }, + { + "id": 45, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 46 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 48 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 46 + }, + { + "name": "E", + "type": 48 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 46, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "bucket_id", + "type": 9, + "typeName": "BucketId" + }, + { + "name": "bucket", + "type": 47, + "typeName": "BucketInStatus" + }, + { + "name": "params", + "type": 16, + "typeName": "BucketParams" + }, + { + "name": "writer_ids", + "type": 14, + "typeName": "Vec" + }, + { + "name": "reader_ids", + "type": 14, + "typeName": "Vec" + }, + { + "name": "rent_covered_until_ms", + "type": 23, + "typeName": "u64" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "bucket", + "entity", + "BucketStatus" + ] + } + }, + { + "id": 47, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "owner_id", + "type": 8, + "typeName": "AccountId" + }, + { + "name": "cluster_id", + "type": 9, + "typeName": "ClusterId" + }, + { + "name": "resource_reserved", + "type": 9, + "typeName": "Resource" + }, + { + "name": "public_availability", + "type": 3, + "typeName": "bool" + }, + { + "name": "resource_consumption_cap", + "type": 9, + "typeName": "Resource" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "bucket", + "entity", + "BucketInStatus" + ] + } + }, + { + "id": 48, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 0, + "name": "BucketDoesNotExist" + }, + { + "index": 1, + "name": "ClusterDoesNotExist" + }, + { + "index": 2, + "name": "ParamsTooBig" + }, + { + "index": 3, + "name": "VNodeDoesNotExist" + }, + { + "index": 4, + "name": "BondingPeriodNotFinished" + }, + { + "index": 5, + "name": "BucketClusterAlreadyConnected" + }, + { + "index": 6, + "name": "BucketClusterNotSetup" + }, + { + "index": 7, + "name": "NodeDoesNotExist" + }, + { + "index": 8, + "name": "NodeAlreadyExists" + }, + { + "index": 9, + "name": "FlowDoesNotExist" + }, + { + "index": 10, + "name": "AccountDoesNotExist" + }, + { + "index": 11, + "name": "ParamsDoesNotExist" + }, + { + "index": 12, + "name": "UnauthorizedProvider" + }, + { + "index": 13, + "name": "UnauthorizedOwner" + }, + { + "index": 14, + "name": "UnauthorizedClusterManager" + }, + { + "index": 15, + "name": "ClusterManagerIsNotTrusted" + }, + { + "index": 16, + "name": "TransferFailed" + }, + { + "index": 17, + "name": "InsufficientBalance" + }, + { + "index": 18, + "name": "InsufficientResources" + }, + { + "index": 19, + "name": "Unauthorized" + }, + { + "index": 20, + "name": "UnknownNode" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "Error" + ] + } + }, + { + "id": 49, + "type": { + "def": { + "tuple": [ + 50, + 9 + ] + } + } + }, + { + "id": 50, + "type": { + "def": { + "sequence": { + "type": 46 + } + } + } + }, + { + "id": 51, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 52 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 48 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 52 + }, + { + "name": "E", + "type": 48 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 52, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "cluster_id", + "type": 9, + "typeName": "ClusterId" + }, + { + "name": "cluster", + "type": 18, + "typeName": "Cluster" + }, + { + "name": "params", + "type": 16, + "typeName": "Params" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "cluster", + "entity", + "ClusterStatus" + ] + } + }, + { + "id": 53, + "type": { + "def": { + "tuple": [ + 54, + 9 + ] + } + } + }, + { + "id": 54, + "type": { + "def": { + "sequence": { + "type": 52 + } + } + } + }, + { + "id": 55, + "type": { + "def": { + "sequence": { + "type": 56 + } + } + } + }, + { + "id": 56, + "type": { + "def": { + "tuple": [ + 8, + 12 + ] + } + } + }, + { + "id": 57, + "type": { + "def": { + "sequence": { + "type": 58 + } + } + } + }, + { + "id": 58, + "type": { + "def": { + "tuple": [ + 9, + 12 + ] + } + } + }, + { + "id": 59, + "type": { + "def": { + "sequence": { + "type": 60 + } + } + } + }, + { + "id": 60, + "type": { + "def": { + "tuple": [ + 9, + 9 + ] + } + } + }, + { + "id": 61, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 62 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 48 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 62 + }, + { + "name": "E", + "type": 48 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 62, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "cluster_id", + "type": 9, + "typeName": "ClusterId" + }, + { + "name": "cluster", + "type": 25, + "typeName": "CdnCluster" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "cdn_cluster", + "entity", + "CdnClusterStatus" + ] + } + }, + { + "id": 63, + "type": { + "def": { + "tuple": [ + 64, + 9 + ] + } + } + }, + { + "id": 64, + "type": { + "def": { + "sequence": { + "type": 62 + } + } + } + }, + { + "id": 65, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "start", + "type": 23, + "typeName": "u64" + }, + { + "name": "interval", + "type": 23, + "typeName": "u64" + }, + { + "name": "commit_duration", + "type": 23, + "typeName": "u64" + }, + { + "name": "validation_duration", + "type": 23, + "typeName": "u64" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "committer", + "store", + "EraConfig" + ] + } + }, + { + "id": 66, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "current_era", + "type": 23, + "typeName": "u64" + }, + { + "name": "current_phase", + "type": 67, + "typeName": "Phase" + }, + { + "name": "previous_era", + "type": 23, + "typeName": "u64" + }, + { + "name": "prev_era_from_timestamp", + "type": 23, + "typeName": "u64" + }, + { + "name": "prev_era_to_timestamp", + "type": 23, + "typeName": "u64" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "committer", + "store", + "EraStatus" + ] + } + }, + { + "id": 67, + "type": { + "def": { + "variant": { + "variants": [ + { + "index": 0, + "name": "Commit" + }, + { + "index": 1, + "name": "Valiadation" + }, + { + "index": 2, + "name": "Payout" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "committer", + "store", + "Phase" + ] + } + }, + { + "id": 68, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 69 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 48 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 69 + }, + { + "name": "E", + "type": 48 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 69, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "node_id", + "type": 9, + "typeName": "NodeId" + }, + { + "name": "node", + "type": 27, + "typeName": "CdnNode" + }, + { + "name": "params", + "type": 16, + "typeName": "Params" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "cdn_node", + "entity", + "CdnNodeStatus" + ] + } + }, + { + "id": 70, + "type": { + "def": { + "tuple": [ + 71, + 9 + ] + } + } + }, + { + "id": 71, + "type": { + "def": { + "sequence": { + "type": 69 + } + } + } + }, + { + "id": 72, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 73 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 48 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 73 + }, + { + "name": "E", + "type": 48 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 73, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "node_id", + "type": 9, + "typeName": "NodeId" + }, + { + "name": "node", + "type": 30, + "typeName": "Node" + }, + { + "name": "params", + "type": 16, + "typeName": "Params" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "node", + "entity", + "NodeStatus" + ] + } + }, + { + "id": 74, + "type": { + "def": { + "tuple": [ + 75, + 9 + ] + } + } + }, + { + "id": 75, + "type": { + "def": { + "sequence": { + "type": 73 + } + } + } + }, + { + "id": 76, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 33 + } + ], + "index": 0, + "name": "Ok" + }, + { + "fields": [ + { + "type": 48 + } + ], + "index": 1, + "name": "Err" + } + ] + } + }, + "params": [ + { + "name": "T", + "type": 33 + }, + { + "name": "E", + "type": 48 + } + ], + "path": [ + "Result" + ] + } + }, + { + "id": 77, + "type": { + "def": { + "variant": { + "variants": [ + { + "fields": [ + { + "type": 8, + "typeName": "AccountId" + } + ], + "index": 0, + "name": "ManagerTrustedBy" + }, + { + "index": 1, + "name": "SetExchangeRate" + }, + { + "index": 2, + "name": "SuperAdmin" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "perm", + "entity", + "Permission" + ] + } + }, + { + "id": 78, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "network_fee_bp", + "type": 12, + "typeName": "BasisPoints" + }, + { + "name": "network_fee_destination", + "type": 8, + "typeName": "AccountId" + }, + { + "name": "cluster_management_fee_bp", + "type": 12, + "typeName": "BasisPoints" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "network_fee", + "FeeConfig" + ] + } + } + ] + } +} \ No newline at end of file diff --git a/bucket/scripts/package-lock.json b/bucket/scripts/package-lock.json new file mode 100644 index 00000000..0411d6de --- /dev/null +++ b/bucket/scripts/package-lock.json @@ -0,0 +1,789 @@ +{ + "name": "scripts", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@polkadot/api": "^10.9.1", + "@polkadot/api-contract": "^10.9.1", + "@polkadot/util-crypto": "^12.3.2" + } + }, + "node_modules/@noble/curves": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", + "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "dependencies": { + "@noble/hashes": "1.3.1" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@polkadot/api": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-10.9.1.tgz", + "integrity": "sha512-ND/2UqZBWvtt4PfV03OStTKg0mxmPk4UpMAgJKutdgsz/wP9CYJ1KbjwFgPNekL9JnzbKQsWyQNPVrcw7kQk8A==", + "dependencies": { + "@polkadot/api-augment": "10.9.1", + "@polkadot/api-base": "10.9.1", + "@polkadot/api-derive": "10.9.1", + "@polkadot/keyring": "^12.3.1", + "@polkadot/rpc-augment": "10.9.1", + "@polkadot/rpc-core": "10.9.1", + "@polkadot/rpc-provider": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-augment": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/types-create": "10.9.1", + "@polkadot/types-known": "10.9.1", + "@polkadot/util": "^12.3.1", + "@polkadot/util-crypto": "^12.3.1", + "eventemitter3": "^5.0.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/api-augment": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-10.9.1.tgz", + "integrity": "sha512-kRZZvCFVcN4hAH4dJ+Qzfdy27/4EEq3oLDf3ihj0LTVrAezSWcKPGE3EVFy+Mn6Lo4SUc7RVyoKvIUhSk2l4Dg==", + "dependencies": { + "@polkadot/api-base": "10.9.1", + "@polkadot/rpc-augment": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-augment": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/api-base": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-10.9.1.tgz", + "integrity": "sha512-Q3m2KzlceMK2kX8bhnUZWk3RT6emmijeeFZZQgCePpEcrSeNjnqG4qjuTPgkveaOkUT8MAoDc5Avuzcc2jlW9g==", + "dependencies": { + "@polkadot/rpc-core": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/util": "^12.3.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/api-contract": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-contract/-/api-contract-10.9.1.tgz", + "integrity": "sha512-BJjFYSFtsUlClC3mgvPNQ5h/7LZd5gVfexwl+mDgLd/6SN4dUBQjIXhlIL5a1cGYjq3EROuu7t0agG2DIaiZMQ==", + "dependencies": { + "@polkadot/api": "10.9.1", + "@polkadot/api-augment": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/types-create": "10.9.1", + "@polkadot/util": "^12.3.1", + "@polkadot/util-crypto": "^12.3.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/api-derive": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-10.9.1.tgz", + "integrity": "sha512-mRud1UZCFIc4Z63qAoGSIHh/foyUYADfy1RQYCmPpeFKfIdCIrHpd7xFdJXTOMYOS0BwlM6u4qli/ZT4XigezQ==", + "dependencies": { + "@polkadot/api": "10.9.1", + "@polkadot/api-augment": "10.9.1", + "@polkadot/api-base": "10.9.1", + "@polkadot/rpc-core": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "@polkadot/util-crypto": "^12.3.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/keyring": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-12.3.2.tgz", + "integrity": "sha512-NTdtDeI0DP9l/45hXynNABeP5VB8piw5YR+CbUxK2e36xpJWVXwbcOepzslg5ghE9rs8UKJb30Z/HqTU4sBY0Q==", + "dependencies": { + "@polkadot/util": "12.3.2", + "@polkadot/util-crypto": "12.3.2", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "12.3.2", + "@polkadot/util-crypto": "12.3.2" + } + }, + "node_modules/@polkadot/networks": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-12.3.2.tgz", + "integrity": "sha512-uCkyybKoeEm1daKr0uT/9oNDHDDzCy2/ZdVl346hQqfdR1Ct3BaxMjxqvdmb5N8aCw0cBWSfgsxAYtw8ESmllQ==", + "dependencies": { + "@polkadot/util": "12.3.2", + "@substrate/ss58-registry": "^1.40.0", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/rpc-augment": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-10.9.1.tgz", + "integrity": "sha512-MaLHkNlyqN20ZRYr6uNd1BZr1OsrnX9qLAmsl0mcrri1vPGRH6VHjfFH1RBLkikpWD82v17g0l2hLwdV1ZHMcw==", + "dependencies": { + "@polkadot/rpc-core": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/rpc-core": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-10.9.1.tgz", + "integrity": "sha512-ZtA8B8SfXSAwVkBlCcKRHw0eSM7ec/sbiNOM5GasXPeRujUgT7lOwSH2GbUZSqe9RfRDMp6DvO9c2JoGc3LLWw==", + "dependencies": { + "@polkadot/rpc-augment": "10.9.1", + "@polkadot/rpc-provider": "10.9.1", + "@polkadot/types": "10.9.1", + "@polkadot/util": "^12.3.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/rpc-provider": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-10.9.1.tgz", + "integrity": "sha512-4QzT2QzD+320+eT6b79sGAA85Tt3Bb8fQvse4r5Mom2iiBd2SO81vOhxSAOaIe4GUsw25VzFJmsbe7+OObItdg==", + "dependencies": { + "@polkadot/keyring": "^12.3.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-support": "10.9.1", + "@polkadot/util": "^12.3.1", + "@polkadot/util-crypto": "^12.3.1", + "@polkadot/x-fetch": "^12.3.1", + "@polkadot/x-global": "^12.3.1", + "@polkadot/x-ws": "^12.3.1", + "eventemitter3": "^5.0.1", + "mock-socket": "^9.2.1", + "nock": "^13.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "@substrate/connect": "0.7.26" + } + }, + "node_modules/@polkadot/types": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.9.1.tgz", + "integrity": "sha512-AG33i2ZGGfq7u+5rkAdGrXAQHHl844/Yv+junH5ZzX69xiCoWO1bH/yzDUNBdpki2GlACWvF9nLYh3F2tVF93w==", + "dependencies": { + "@polkadot/keyring": "^12.3.1", + "@polkadot/types-augment": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/types-create": "10.9.1", + "@polkadot/util": "^12.3.1", + "@polkadot/util-crypto": "^12.3.1", + "rxjs": "^7.8.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-augment": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-10.9.1.tgz", + "integrity": "sha512-OY9/jTMFRFqYdkUnfcGwqMLC64A0Q25bjvCuVQCVjsPFKE3wl0Kt5rNT01eV2UmLXrR6fY0xWbR2w80bLA7CIQ==", + "dependencies": { + "@polkadot/types": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-codec": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-10.9.1.tgz", + "integrity": "sha512-mJ5OegKGraY1FLvEa8FopRCr3pQrhDkcn5RNOjmgJQozENVeRaxhk0NwxYz7IojFvSDnKnc6lNQfKaaSe5pLHg==", + "dependencies": { + "@polkadot/util": "^12.3.1", + "@polkadot/x-bigint": "^12.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-create": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-10.9.1.tgz", + "integrity": "sha512-OVz50MGTTuiuVnRP/zAx4CTuLioc0hsiwNwqN2lNhmIJGtnQ4Vy/7mQRsIWehiYz6g0Vzzm5B3qWkTXO1NSN5w==", + "dependencies": { + "@polkadot/types-codec": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-known": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-10.9.1.tgz", + "integrity": "sha512-zCMVWc4pJtkbMFPu72bD4IhvV/gkHXPX3C5uu92WdmCfnn0vEIEsMKWlVXVVvQQZKAqvs/awpqIfrUtEViOGEA==", + "dependencies": { + "@polkadot/networks": "^12.3.1", + "@polkadot/types": "10.9.1", + "@polkadot/types-codec": "10.9.1", + "@polkadot/types-create": "10.9.1", + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/types-support": { + "version": "10.9.1", + "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-10.9.1.tgz", + "integrity": "sha512-XsieuLDsszvMZQlleacQBfx07i/JkwQV/UxH9q8Hz7Okmaz9pEVEW1h3ka2/cPuC7a4l32JhaORBUYshBZNdJg==", + "dependencies": { + "@polkadot/util": "^12.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/util": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-12.3.2.tgz", + "integrity": "sha512-y/JShcGyOamCUiSIg++XZuLHt1ktSKBaSH2K5Nw5NXlgP0+7am+GZzqPB8fQ4qhYLruEOv+YRiz0GC1Zr9S+wg==", + "dependencies": { + "@polkadot/x-bigint": "12.3.2", + "@polkadot/x-global": "12.3.2", + "@polkadot/x-textdecoder": "12.3.2", + "@polkadot/x-textencoder": "12.3.2", + "@types/bn.js": "^5.1.1", + "bn.js": "^5.2.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/util-crypto": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-12.3.2.tgz", + "integrity": "sha512-pTpx+YxolY0BDT4RcGmgeKbHHD/dI6Ll9xRsqmVdIjpcVVY20uDNTyXs81ZNtfKgyod1y9JQkfNv2Dz9iEpTkQ==", + "dependencies": { + "@noble/curves": "1.1.0", + "@noble/hashes": "1.3.1", + "@polkadot/networks": "12.3.2", + "@polkadot/util": "12.3.2", + "@polkadot/wasm-crypto": "^7.2.1", + "@polkadot/wasm-util": "^7.2.1", + "@polkadot/x-bigint": "12.3.2", + "@polkadot/x-randomvalues": "12.3.2", + "@scure/base": "1.1.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "12.3.2" + } + }, + "node_modules/@polkadot/wasm-bridge": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.2.1.tgz", + "integrity": "sha512-uV/LHREDBGBbHrrv7HTki+Klw0PYZzFomagFWII4lp6Toj/VCvRh5WMzooVC+g/XsBGosAwrvBhoModabyHx+A==", + "dependencies": { + "@polkadot/wasm-util": "7.2.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/wasm-crypto": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-7.2.1.tgz", + "integrity": "sha512-SA2+33S9TAwGhniKgztVN6pxUKpGfN4Tre/eUZGUfpgRkT92wIUT2GpGWQE+fCCqGQgADrNiBcwt6XwdPqMQ4Q==", + "dependencies": { + "@polkadot/wasm-bridge": "7.2.1", + "@polkadot/wasm-crypto-asmjs": "7.2.1", + "@polkadot/wasm-crypto-init": "7.2.1", + "@polkadot/wasm-crypto-wasm": "7.2.1", + "@polkadot/wasm-util": "7.2.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/wasm-crypto-asmjs": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.2.1.tgz", + "integrity": "sha512-z/d21bmxyVfkzGsKef/FWswKX02x5lK97f4NPBZ9XBeiFkmzlXhdSnu58/+b1sKsRAGdW/Rn/rTNRDhW0GqCAg==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/wasm-crypto-init": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.2.1.tgz", + "integrity": "sha512-GcEXtwN9LcSf32V9zSaYjHImFw16hCyo2Xzg4GLLDPPeaAAfbFr2oQMgwyDbvBrBjLKHVHjsPZyGhXae831amw==", + "dependencies": { + "@polkadot/wasm-bridge": "7.2.1", + "@polkadot/wasm-crypto-asmjs": "7.2.1", + "@polkadot/wasm-crypto-wasm": "7.2.1", + "@polkadot/wasm-util": "7.2.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*", + "@polkadot/x-randomvalues": "*" + } + }, + "node_modules/@polkadot/wasm-crypto-wasm": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.2.1.tgz", + "integrity": "sha512-DqyXE4rSD0CVlLIw88B58+HHNyrvm+JAnYyuEDYZwCvzUWOCNos/DDg9wi/K39VAIsCCKDmwKqkkfIofuOj/lA==", + "dependencies": { + "@polkadot/wasm-util": "7.2.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/wasm-util": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.2.1.tgz", + "integrity": "sha512-FBSn/3aYJzhN0sYAYhHB8y9JL8mVgxLy4M1kUXYbyo+8GLRQEN5rns8Vcb8TAlIzBWgVTOOptYBvxo0oj0h7Og==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "*" + } + }, + "node_modules/@polkadot/x-bigint": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-12.3.2.tgz", + "integrity": "sha512-JLqLgfGXe/x+hZJETd5ZqfpVsbwyMsH5Nn1Q20ineMMjXN/ig+kVR8Mc15LXBMuw4g7LldFW6UUrotWnuMI8Yw==", + "dependencies": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/x-fetch": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-12.3.2.tgz", + "integrity": "sha512-3IEuZ5S+RI/t33NsdPLIIa5COfDCfpUW2sbaByEczn75aD1jLqJZSEDwiBniJ2osyNd4uUxBf6e5jw7LAZeZJg==", + "dependencies": { + "@polkadot/x-global": "12.3.2", + "node-fetch": "^3.3.1", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/x-global": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-12.3.2.tgz", + "integrity": "sha512-yVZq6oIegjlyh5rUZiTklgu+fL+W/DG1ypEa02683tUCB3avV5cA3PAHKptMSlb6FpweHu37lKKrqfAWrraDxg==", + "dependencies": { + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/x-randomvalues": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-12.3.2.tgz", + "integrity": "sha512-ywjIs8CWpvOGmq+3cGCNPOHxAjPHdBUiXyDccftx5BRVdmtbt36gK/V84bKr6Xs73FGu0jprUAOSRRsLZX/3dg==", + "dependencies": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "@polkadot/util": "12.3.2", + "@polkadot/wasm-util": "*" + } + }, + "node_modules/@polkadot/x-textdecoder": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-12.3.2.tgz", + "integrity": "sha512-lY5bfA5xArJRWEJlYOlQQMJeTjWD8s0yMhchirVgf5xj8Id9vPGeUoneH+VFDEwgXxrqBvDFJ4smN4T/r6a/fg==", + "dependencies": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/x-textencoder": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-12.3.2.tgz", + "integrity": "sha512-iP3qEBiHzBckQ9zeY7ZHRWuu7mCEg5SMpOugs6UODRk8sx6KHzGQYlghBbWLit0uppPDVE0ifEwZ2n73djJHWQ==", + "dependencies": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@polkadot/x-ws": { + "version": "12.3.2", + "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-12.3.2.tgz", + "integrity": "sha512-yM9Z64pLNlHpJE43+Xtr+iUXmYpFFY5u5hrke2PJt13O48H8f9Vb9cRaIh94appLyICoS0aekGhDkGH+MCspBA==", + "dependencies": { + "@polkadot/x-global": "12.3.2", + "tslib": "^2.5.3", + "ws": "^8.13.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@scure/base": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", + "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "node_modules/@substrate/connect": { + "version": "0.7.26", + "resolved": "https://registry.npmjs.org/@substrate/connect/-/connect-0.7.26.tgz", + "integrity": "sha512-uuGSiroGuKWj1+38n1kY5HReer5iL9bRwPCzuoLtqAOmI1fGI0hsSI2LlNQMAbfRgr7VRHXOk5MTuQf5ulsFRw==", + "optional": true, + "dependencies": { + "@substrate/connect-extension-protocol": "^1.0.1", + "eventemitter3": "^4.0.7", + "smoldot": "1.0.4" + } + }, + "node_modules/@substrate/connect-extension-protocol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-1.0.1.tgz", + "integrity": "sha512-161JhCC1csjH3GE5mPLEd7HbWtwNSPJBg3p1Ksz9SFlTzj/bgEwudiRN2y5i0MoLGCIJRYKyKGMxVnd29PzNjg==", + "optional": true + }, + "node_modules/@substrate/connect/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "optional": true + }, + "node_modules/@substrate/ss58-registry": { + "version": "1.40.0", + "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.40.0.tgz", + "integrity": "sha512-QuU2nBql3J4KCnOWtWDw4n1K4JU0T79j54ZZvm/9nhsX6AIar13FyhsaBfs6QkJ2ixTQAnd7TocJIoJRWbqMZA==" + }, + "node_modules/@types/bn.js": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz", + "integrity": "sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "20.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz", + "integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==" + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/mock-socket": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.2.1.tgz", + "integrity": "sha512-aw9F9T9G2zpGipLLhSNh6ZpgUyUl4frcVmRN08uE1NWPWg43Wx6+sGPDbQ7E5iFZZDJW5b5bypMeAEHqTbIFag==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nock": { + "version": "13.3.1", + "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.1.tgz", + "integrity": "sha512-vHnopocZuI93p2ccivFyGuUfzjq2fxNyNurp7816mlT5V5HF4SzXu8lvLrVzBbNqzs+ODooZ6OksuSUNM7Njkw==", + "dependencies": { + "debug": "^4.1.0", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.21", + "propagate": "^2.0.0" + }, + "engines": { + "node": ">= 10.13" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", + "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "optional": true + }, + "node_modules/propagate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", + "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/smoldot": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-1.0.4.tgz", + "integrity": "sha512-N3TazI1C4GGrseFH/piWyZCCCRJTRx2QhDfrUKRT4SzILlW5m8ayZ3QTKICcz1C/536T9cbHHJyP7afxI6Mi1A==", + "optional": true, + "dependencies": { + "pako": "^2.0.4", + "ws": "^8.8.1" + } + }, + "node_modules/tslib": { + "version": "2.5.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", + "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" + }, + "node_modules/web-streams-polyfill": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", + "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/ws": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + } + } +} diff --git a/bucket/scripts/package.json b/bucket/scripts/package.json new file mode 100644 index 00000000..bc305466 --- /dev/null +++ b/bucket/scripts/package.json @@ -0,0 +1,8 @@ +{ + "type": "module", + "dependencies": { + "@polkadot/api": "^10.9.1", + "@polkadot/api-contract": "^10.9.1", + "@polkadot/util-crypto": "^12.3.2" + } +} From b695625d20d7e689041196b31faa0349ebc42d5f Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Sat, 1 Jul 2023 01:58:56 +0200 Subject: [PATCH 77/89] chore(scripts): ddc setup script is moved to scripts folder --- bucket/scripts/.gitignore | 2 - bucket/scripts/init.js | 129 - bucket/scripts/metadata.json | 4959 ----------------- bucket/scripts/package-lock.json | 789 --- bucket/scripts/package.json | 8 - scripts/.gitignore | 3 +- .../ddc-setup/ddcConfig.js | 2 +- scripts/ddc-setup/ddcSetup.js | 147 + scripts/deployment/deploy.js | 2 +- scripts/examples/ddcBucketDemo.js | 2 +- scripts/examples/ddcBucketPrint.js | 2 +- scripts/examples/ddcNftRegistryDemo.js | 2 +- scripts/package.json | 3 +- scripts/sdk/src/deploymentRegistry.js | 13 +- scripts/sdk/src/polkadotWrappers.js | 11 +- 15 files changed, 175 insertions(+), 5899 deletions(-) delete mode 100644 bucket/scripts/.gitignore delete mode 100644 bucket/scripts/init.js delete mode 100644 bucket/scripts/metadata.json delete mode 100644 bucket/scripts/package-lock.json delete mode 100644 bucket/scripts/package.json rename bucket/scripts/config.js => scripts/ddc-setup/ddcConfig.js (99%) create mode 100644 scripts/ddc-setup/ddcSetup.js diff --git a/bucket/scripts/.gitignore b/bucket/scripts/.gitignore deleted file mode 100644 index 1929c324..00000000 --- a/bucket/scripts/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/ -secrets.txt diff --git a/bucket/scripts/init.js b/bucket/scripts/init.js deleted file mode 100644 index 281fe009..00000000 --- a/bucket/scripts/init.js +++ /dev/null @@ -1,129 +0,0 @@ -import { config } from './config.js'; -import * as fs from 'fs'; - -import { ContractPromise } from '@polkadot/api-contract'; -import { ApiPromise, WsProvider, Keyring } from '@polkadot/api'; -import { cryptoWaitReady, mnemonicGenerate } from "@polkadot/util-crypto"; - -const INIT_ENV = process.env.INIT_ENV; -const SUPERADMIN_MNEMONIC = process.env.SUPERADMIN; -const CERE = 10_000_000_000n; - -const txOptions = { - storageDepositLimit: null, - gasLimit: 100_000_000_000n, -}; - -async function signAndSendPromise(txn, signer) { - return new Promise((res, rej) => { - txn - .signAndSend(signer, ({ events = [], status, blockNumber }) => { - if (status.isInvalid) { - console.log(" Transaction invalid"); - rej("Transaction invalid"); - } else if (status.isReady) { - console.log(" Transaction is ready"); - } else if (status.isBroadcast) { - console.log(" Transaction has been broadcasted"); - } else if (status.isInBlock) { - const blockHash = status.asInBlock.toHex(); - console.log(` Transaction is in block: ${blockHash} of ${blockNumber}`); - } else if (status.isFinalized) { - const blockHash = status.asFinalized.toHex(); - console.log(` Transaction has been included in blockHash ${blockHash} of ${blockNumber}`); - const treasuryDeposit = events.find( - (event) => event.event.toHuman().method === "Deposit" && event.event.toHuman().section === "treasury", - ); - const txFee = treasuryDeposit ? treasuryDeposit.event.toHuman().data.value : undefined; - const txFeeParsed = txFee ? (parseFloat(txFee.replace(" mCERE", "")) / 1000) * 2 : undefined; - - if (events.find(event => event.event.toHuman().method === "ExtrinsicSuccess")) res({ blockHash, txFeeParsed, events }); - else rej("No success found: " + blockHash); - } - }) - .catch((err) => rej(err)); - }); -} - -function createUser() { - const keyring = new Keyring({ type: "sr25519" }); - const mnemonic = mnemonicGenerate(12); - const account = keyring.addFromUri(mnemonic); - - return { - mnemonic: mnemonic, - address: account.address, - addressBase64: Buffer.from(account.publicKey).toString("base64"), - }; -} - -const cfg = config[INIT_ENV]; -if (cfg === undefined) { - console.error("Please provide INIT_ENV as one of ", Object.keys(config)); - process.exit(-1); -} -console.log(cfg); - -await cryptoWaitReady(); -const keyring = new Keyring({ type: "sr25519" }); -const alice = keyring.addFromUri("//Alice"); -const sadmin = keyring.addFromUri(SUPERADMIN_MNEMONIC); -console.log(`Superadmin: ${sadmin.address}`); - -// Contract metadata -const metadata = fs.readFileSync('./metadata.json', 'utf8'); - -// Construct -const wsProvider = new WsProvider(cfg.ws_provider); -const api = await ApiPromise.create({ provider: wsProvider }); -const contract = new ContractPromise(api, metadata, cfg.contract_address); - -console.log("1. adminGrantPermission"); -const res = await signAndSendPromise(await contract.tx.adminGrantPermission(txOptions, sadmin.address, "SuperAdmin"), sadmin); - -console.log("2. accountSetUsdPerCere"); -await signAndSendPromise(await contract.tx.accountSetUsdPerCere(txOptions, 1000n * CERE), sadmin); - -console.log("3. cdnNodeTrustManager"); -await signAndSendPromise(await contract.tx.cdnNodeTrustManager(txOptions, sadmin.address), sadmin); - -console.log("4. nodeTrustManager"); -await signAndSendPromise(await contract.tx.nodeTrustManager(txOptions, sadmin.address), sadmin); - -console.log("5. cdnNodeCreate"); -for (let i = 0; i < cfg.cdn_node_params.length; i++) { - await signAndSendPromise(await contract.tx.cdnNodeCreate(txOptions, JSON.stringify(cfg.cdn_node_params[i])), sadmin); -} - -for (let id in cfg.cdn_cluster) { - const clu = cfg.cdn_cluster[id]; - console.log("6. cdnClusterCreate, cluster: ", id, clu); - await signAndSendPromise(await contract.tx.cdnClusterCreate(txOptions, clu.cdn_nodes), sadmin); -} - -console.log("7. nodeCreate"); -for (let i = 0; i < cfg.storage_node_params.length; i++) { - const param = JSON.stringify(cfg.storage_node_params[i]); - const user = createUser(); - fs.appendFileSync('secrets.txt', `${user.address}: ${user.mnemonic} -- ${INIT_ENV} storage ${i}\n`); - console.log(` node ${i}: address ${user.address}, param ${param}`); - await signAndSendPromise(await contract.tx.nodeCreate(txOptions, 1n * CERE, param, 100000n, "ACTIVE", user.address), sadmin); -} - -for (let id in cfg.cluster) { - const clu = cfg.cluster[id]; - - console.log("8. clusterCreate, cluster: ", id, clu); - await signAndSendPromise(await contract.tx.clusterCreate(txOptions, alice.address, clu.vnodes, clu.storage_nodes, JSON.stringify(clu.param)), sadmin); - - console.log("9. clusterReserveResource, cluster: ", id); - await signAndSendPromise(await contract.tx.clusterReserveResource(txOptions, id, 100000n), sadmin); -} - -// console.log("cdnNodeChangeParams"); -// for (let i = 0; i < cfg.cdn_node_params.length; i++) { -// await signAndSendPromise(await contract.tx.cdnNodeChangeParams(txOptions, i+1, JSON.stringify(cfg.cdn_node_params[i])), sadmin); -// } - -//console.log(res.events.map(event => event.event.toHuman())); -process.exit(0); diff --git a/bucket/scripts/metadata.json b/bucket/scripts/metadata.json deleted file mode 100644 index 5233dd85..00000000 --- a/bucket/scripts/metadata.json +++ /dev/null @@ -1,4959 +0,0 @@ -{ - "source": { - "hash": "0x17173e6d800d4555fa6b27c1cb7a5bf509796c993c1ed7e1206e8ef27c21fb48", - "language": "ink! 3.4.0", - "compiler": "rustc 1.69.0-nightly" - }, - "contract": { - "name": "ddc_bucket", - "version": "0.5.2", - "authors": [ - "Aurélien Nicolas " - ], - "description": "DDC v2 Smart Contracts -- Orchestrate the network around clusters and buckets", - "license": "Apache-2.0" - }, - "V3": { - "spec": { - "constructors": [ - { - "args": [], - "docs": [ - "Create a new contract.", - "", - "The caller will be admin of the contract." - ], - "label": "new", - "payable": false, - "selector": "0x9bae9d5e" - } - ], - "docs": [], - "events": [ - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "owner_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " A bucket was created. The given account is its first owner and payer of resources." - ], - "label": "BucketCreated" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": false, - "label": "resource", - "type": { - "displayName": [ - "Resource" - ], - "type": 9 - } - } - ], - "docs": [ - " Some amount of resources of a cluster were allocated to a bucket." - ], - "label": "BucketAllocated" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - } - ], - "docs": [ - " The due costs of a bucket was settled from the bucket payer to the cluster." - ], - "label": "BucketSettlePayment" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "public_availability", - "type": { - "displayName": [ - "bool" - ], - "type": 3 - } - } - ], - "docs": [ - " The availiablity of the bucket was updated." - ], - "label": "BucketAvailabilityUpdated" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "manager", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "docs": [], - "indexed": false, - "label": "cluster_params", - "type": { - "displayName": [ - "ClusterParams" - ], - "type": 16 - } - } - ], - "docs": [ - " A new cluster was created." - ], - "label": "ClusterCreated" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - } - ], - "docs": [ - " A vnode was re-assigned to new node." - ], - "label": "ClusterNodeReplaced" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": false, - "label": "resource", - "type": { - "displayName": [ - "Resource" - ], - "type": 9 - } - } - ], - "docs": [ - " Some resources were reserved for the cluster from the nodes." - ], - "label": "ClusterReserveResource" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "provider_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " The share of revenues of a cluster for a provider was distributed." - ], - "label": "ClusterDistributeRevenues" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "manager", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " A new cluster was created." - ], - "label": "CdnClusterCreated" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "provider_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " The respective share of revenues of a CDN cluster for a provider was distributed." - ], - "label": "CdnClusterDistributeRevenues" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "provider_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "docs": [], - "indexed": false, - "label": "undistributed_payment", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - } - ], - "docs": [ - " A node was created. The given account is its owner and recipient of revenues." - ], - "label": "CdnNodeCreated" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "provider_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "docs": [], - "indexed": false, - "label": "rent_per_month", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - }, - { - "docs": [], - "indexed": false, - "label": "node_params", - "type": { - "displayName": [ - "NodeParams" - ], - "type": 16 - } - } - ], - "docs": [ - " A node was created. The given account is its owner and recipient of revenues." - ], - "label": "NodeCreated" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "account_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "docs": [], - "indexed": false, - "label": "value", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - } - ], - "docs": [ - " Tokens were deposited on an account." - ], - "label": "Deposit" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "account_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "docs": [], - "indexed": false, - "label": "permission", - "type": { - "displayName": [ - "Permission" - ], - "type": 77 - } - } - ], - "docs": [ - " A permission was granted to the account." - ], - "label": "GrantPermission" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "account_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "docs": [], - "indexed": false, - "label": "permission", - "type": { - "displayName": [ - "Permission" - ], - "type": 77 - } - } - ], - "docs": [ - " A permission was revoked from the account." - ], - "label": "RevokePermission" - } - ], - "messages": [ - { - "args": [ - { - "label": "bucket_params", - "type": { - "displayName": [ - "BucketParams" - ], - "type": 16 - } - }, - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "owner_id", - "type": { - "displayName": [ - "Option" - ], - "type": 43 - } - } - ], - "docs": [ - " Create a new bucket and return its `bucket_id`.", - "", - " The caller will be its first owner and payer of resources.", - "", - " `bucket_params` is configuration used by clients and nodes. See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema)", - "", - " The bucket can be connected to a single cluster (currently). Allocate cluster resources with the function `bucket_alloc_into_cluster`" - ], - "label": "bucket_create", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [ - "BucketId" - ], - "type": 9 - }, - "selector": "0x0aeb2379" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "owner_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Change owner of the bucket", - "", - " Provide the account of new owner" - ], - "label": "bucket_change_owner", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xc7d0c2cd" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "resource", - "type": { - "displayName": [ - "Resource" - ], - "type": 9 - } - } - ], - "docs": [ - " Allocate some resources of a cluster to a bucket.", - "", - " The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes)." - ], - "label": "bucket_alloc_into_cluster", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x4c482d19" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - } - ], - "docs": [ - " Settle the due costs of a bucket from its payer account to the cluster account." - ], - "label": "bucket_settle_payment", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0x15974555" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "params", - "type": { - "displayName": [ - "BucketParams" - ], - "type": 16 - } - } - ], - "docs": [ - " Change the `bucket_params`, which is configuration used by clients and nodes.", - "", - " See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "bucket_change_params", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x9f2d075b" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - } - ], - "docs": [ - " Get the current status of a bucket." - ], - "label": "bucket_get", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 45 - }, - "selector": "0x3802cb77" - }, - { - "args": [ - { - "label": "offset", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "limit", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "filter_owner_id", - "type": { - "displayName": [ - "Option" - ], - "type": 43 - } - } - ], - "docs": [ - " Iterate through all buckets.", - "", - " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", - " The optimal `limit` depends on the size of params.", - "", - " The results can be filtered by owner. Note that paging must still be completed fully." - ], - "label": "bucket_list", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [], - "type": 49 - }, - "selector": "0x417ab584" - }, - { - "args": [ - { - "label": "owner_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Iterate through all buckets and return only those owned by owner", - "", - " This method returns bucket struct, not the status" - ], - "label": "bucket_list_for_account", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Vec" - ], - "type": 6 - }, - "selector": "0xc434cf57" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "public_availability", - "type": { - "displayName": [ - "bool" - ], - "type": 3 - } - } - ], - "docs": [ - " Set availiablity of the bucket" - ], - "label": "bucket_set_availability", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x053eb3ce" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "new_resource_cap", - "type": { - "displayName": [ - "Resource" - ], - "type": 9 - } - } - ], - "docs": [ - " Set max resource cap to be charged by CDN for public bucket" - ], - "label": "bucket_set_resource_cap", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x85010c6d" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - } - ], - "docs": [ - " Set permission for the reader of the bucket" - ], - "label": "get_bucket_writers", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [ - "Vec" - ], - "type": 14 - }, - "selector": "0x499cd4b7" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "writer", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Set permission for the writer of the bucket" - ], - "label": "bucket_set_writer_perm", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xea2e477a" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "writer", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Revoke permission for the writer of the bucket" - ], - "label": "bucket_revoke_writer_perm", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x2b3d8dd1" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - } - ], - "docs": [ - " Set permission for the reader of the bucket" - ], - "label": "get_bucket_readers", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [ - "Vec" - ], - "type": 14 - }, - "selector": "0xb9a7cc1c" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "reader", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Set permission for the reader of the bucket" - ], - "label": "bucket_set_reader_perm", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xfc0e94ea" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "writer", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Revoke permission for the reader of the bucket" - ], - "label": "bucket_revoke_reader_perm", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xe9bfed5a" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "node_ids", - "type": { - "displayName": [ - "Vec" - ], - "type": 20 - } - }, - { - "label": "v_nodes", - "type": { - "displayName": [ - "Vec" - ], - "type": 21 - } - } - ], - "docs": [ - " Removes a node to an existing cluster", - "", - " The caller will be its first manager." - ], - "label": "cluster_remove_node", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x793e0778" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "node_ids", - "type": { - "displayName": [ - "Vec" - ], - "type": 20 - } - }, - { - "label": "v_nodes", - "type": { - "displayName": [ - "Vec" - ], - "type": 21 - } - } - ], - "docs": [ - " Adds node to an existing cluster", - "", - " The caller will be its first manager." - ], - "label": "cluster_add_node", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0xf7496bdc" - }, - { - "args": [ - { - "label": "_unused", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "label": "v_nodes", - "type": { - "displayName": [ - "Vec" - ], - "type": 21 - } - }, - { - "label": "node_ids", - "type": { - "displayName": [ - "Vec" - ], - "type": 20 - } - }, - { - "label": "cluster_params", - "type": { - "displayName": [ - "ClusterParams" - ], - "type": 16 - } - } - ], - "docs": [ - " Create a new cluster and return its `cluster_id`.", - "", - " The caller will be its first manager.", - "", - " The cluster is split in a number of vnodes. The vnodes are assigned to the given physical nodes in a round-robin. Only nodes of providers that trust the cluster manager can be used (see `node_trust_manager`). The assignment can be changed with the function `cluster_replace_node`.", - "", - " `cluster_params` is configuration used by clients and nodes. In particular, this describes the semantics of vnodes. See the [data structure of ClusterParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "cluster_create", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [ - "ClusterId" - ], - "type": 9 - }, - "selector": "0x4c0f21f6" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "amount", - "type": { - "displayName": [ - "Resource" - ], - "type": 9 - } - } - ], - "docs": [ - " As manager, reserve more resources for the cluster from the free capacity of nodes.", - "", - " The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes)." - ], - "label": "cluster_reserve_resource", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xb5e38125" - }, - { - "args": [ - { - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - }, - { - "label": "new_tag", - "type": { - "displayName": [ - "NodeTag" - ], - "type": 31 - } - } - ], - "docs": [ - " As manager, change a node tag" - ], - "label": "cluster_change_node_tag", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x9640d48e" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "v_nodes", - "type": { - "displayName": [ - "Vec" - ], - "type": 22 - } - }, - { - "label": "new_node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - } - ], - "docs": [ - " As manager, re-assign a vnode to another physical node.", - "", - " The cluster manager can only use nodes of providers that trust him (see `node_trust_manager`), or any nodes if he is also SuperAdmin." - ], - "label": "cluster_replace_node", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x48194ab1" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - } - ], - "docs": [ - " Trigger the distribution of revenues from the cluster to the providers." - ], - "label": "cluster_distribute_revenues", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0xe71e66fc" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "params", - "type": { - "displayName": [ - "ClusterParams" - ], - "type": 16 - } - } - ], - "docs": [ - " Change the `cluster_params`, which is configuration used by clients and nodes.", - "", - " See the [data structure of ClusterParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "cluster_change_params", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x1207912c" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - } - ], - "docs": [ - " Get the current status of a cluster." - ], - "label": "cluster_get", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 51 - }, - "selector": "0xe75411f5" - }, - { - "args": [ - { - "label": "offset", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "limit", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "filter_manager_id", - "type": { - "displayName": [ - "Option" - ], - "type": 43 - } - } - ], - "docs": [ - " Iterate through all clusters.", - "", - " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", - " The optimal `limit` depends on the size of params.", - "", - " The results can be filtered by manager. Note that paging must still be completed fully." - ], - "label": "cluster_list", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [], - "type": 53 - }, - "selector": "0xd9db9d44" - }, - { - "args": [ - { - "label": "cdn_node_ids", - "type": { - "displayName": [ - "Vec" - ], - "type": 20 - } - } - ], - "docs": [ - " Create a new cluster and return its `cluster_id`.", - "", - " The caller will be its first manager.", - "", - " The CDN node ids are provided, which will form a cluster." - ], - "label": "cdn_cluster_create", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [ - "ClusterId" - ], - "type": 9 - }, - "selector": "0x4344cd7e" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "usd_per_gb", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - } - ], - "docs": [ - " Set rate for streaming (price per gb)" - ], - "label": "cdn_set_rate", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x7578922a" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - } - ], - "docs": [ - " Get rate for streaming (price per gb)" - ], - "label": "cdn_get_rate", - "mutates": false, - "payable": true, - "returnType": { - "displayName": [ - "Balance" - ], - "type": 12 - }, - "selector": "0xa1e3ea8a" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "aggregates_accounts", - "type": { - "displayName": [ - "Vec" - ], - "type": 55 - } - }, - { - "label": "aggregates_nodes", - "type": { - "displayName": [ - "Vec" - ], - "type": 57 - } - }, - { - "label": "aggregates_buckets", - "type": { - "displayName": [ - "Vec" - ], - "type": 59 - } - }, - { - "label": "era", - "type": { - "displayName": [ - "u64" - ], - "type": 23 - } - } - ], - "docs": [ - " As validator, charge payments from users and allocate undistributed payments to CDN nodes.", - "", - " As a result CDN cluster revenue increases, which can be distributed between CDN node providers via method cdn_cluster_distribute_revenues." - ], - "label": "cdn_cluster_put_revenue", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x7219be3f" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - } - ], - "docs": [ - " Trigger the distribution of revenues from the cluster to the CDN node providers.", - "", - " Anyone can call this method.", - "", - " Undistributed payments will be trasnferred, CDN cluster revenue will decrease." - ], - "label": "cdn_cluster_distribute_revenues", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0xfa8d570d" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - } - ], - "docs": [ - " Get the current status of a cluster." - ], - "label": "cdn_cluster_get", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 61 - }, - "selector": "0x4b22fbf1" - }, - { - "args": [ - { - "label": "offset", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "limit", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "filter_manager_id", - "type": { - "displayName": [ - "Option" - ], - "type": 43 - } - } - ], - "docs": [ - " Iterate through all clusters.", - "", - " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", - " The optimal `limit` depends on the size of params.", - "", - " The results can be filtered by manager. Note that paging must still be completed fully." - ], - "label": "cdn_cluster_list", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [], - "type": 63 - }, - "selector": "0xb242a64f" - }, - { - "args": [ - { - "label": "cdn_owner", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - }, - { - "label": "commit", - "type": { - "displayName": [ - "Commit" - ], - "type": 37 - } - } - ], - "docs": [ - " CDN node operator sets the commit for current era." - ], - "label": "set_commit", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0xe445e1fd" - }, - { - "args": [ - { - "label": "cdn_owner", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Return the last commit submitted by CDN node operator" - ], - "label": "get_commit", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Vec" - ], - "type": 35 - }, - "selector": "0x5329f551" - }, - { - "args": [ - { - "label": "node", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - } - ], - "docs": [ - " Return last era validated per CDN node" - ], - "label": "get_validated_commit", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "EraAndTimestamp" - ], - "type": 40 - }, - "selector": "0x7d497bc1" - }, - { - "args": [ - { - "label": "era_config", - "type": { - "displayName": [ - "EraConfig" - ], - "type": 65 - } - } - ], - "docs": [ - " Set the new configs for era" - ], - "label": "set_era", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x49a5b8f7" - }, - { - "args": [], - "docs": [ - " Return current status of an era" - ], - "label": "get_era", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "EraStatus" - ], - "type": 66 - }, - "selector": "0x617f696b" - }, - { - "args": [], - "docs": [ - " Return current era settings" - ], - "label": "get_era_settings", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "EraConfig" - ], - "type": 65 - }, - "selector": "0x84b61468" - }, - { - "args": [ - { - "label": "manager", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " As node provider, authorize a cluster manager to use his nodes." - ], - "label": "cdn_node_trust_manager", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x372daa96" - }, - { - "args": [ - { - "label": "manager", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " As node provider, revoke the authorization of a cluster manager to use his nodes." - ], - "label": "cdn_node_distrust_manager", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0xf67f5438" - }, - { - "args": [ - { - "label": "node_params", - "type": { - "displayName": [ - "Params" - ], - "type": 16 - } - } - ], - "docs": [ - " Create a new node and return its `node_id`.", - "", - " The caller will be its owner.", - "", - " `node_params` is configuration used by clients and nodes. In particular, this contains the URL to the service. See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "cdn_node_create", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [ - "NodeId" - ], - "type": 9 - }, - "selector": "0xe8aa4ade" - }, - { - "args": [ - { - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - }, - { - "label": "params", - "type": { - "displayName": [ - "NodeParams" - ], - "type": 16 - } - } - ], - "docs": [ - " Change the `node_params`, which is configuration used by clients and nodes.", - "", - " See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "cdn_node_change_params", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0xf52c20f5" - }, - { - "args": [ - { - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - } - ], - "docs": [ - " Get the current state of the cdn node" - ], - "label": "cdn_node_get", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 68 - }, - "selector": "0xf9a5a813" - }, - { - "args": [ - { - "label": "offset", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "limit", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "filter_provider_id", - "type": { - "displayName": [ - "Option" - ], - "type": 43 - } - } - ], - "docs": [ - " Iterate through all nodes.", - "", - " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", - " The optimal `limit` depends on the size of params.", - "", - " The results can be filtered by owner. Note that paging must still be completed fully." - ], - "label": "cdn_node_list", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [], - "type": 70 - }, - "selector": "0xf8589aae" - }, - { - "args": [ - { - "label": "manager", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " As node provider, authorize a cluster manager to use his nodes." - ], - "label": "node_trust_manager", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x6fd54a01" - }, - { - "args": [ - { - "label": "manager", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " As node provider, revoke the authorization of a cluster manager to use his nodes." - ], - "label": "node_distrust_manager", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0x40912279" - }, - { - "args": [ - { - "label": "rent_per_month", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - }, - { - "label": "node_params", - "type": { - "displayName": [ - "NodeParams" - ], - "type": 16 - } - }, - { - "label": "capacity", - "type": { - "displayName": [ - "Resource" - ], - "type": 9 - } - }, - { - "label": "node_tag", - "type": { - "displayName": [ - "NodeTag" - ], - "type": 31 - } - }, - { - "label": "pubkey", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Create a new node and return its `node_id`.", - "", - " The caller will be its owner.", - "", - " `node_params` is configuration used by clients and nodes. In particular, this contains the URL to the service. See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "node_create", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [ - "NodeId" - ], - "type": 9 - }, - "selector": "0xb77ac1bb" - }, - { - "args": [ - { - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - }, - { - "label": "params", - "type": { - "displayName": [ - "NodeParams" - ], - "type": 16 - } - } - ], - "docs": [ - " Change the `node_params`, which is configuration used by clients and nodes.", - "", - " See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "node_change_params", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x258ccb2a" - }, - { - "args": [ - { - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - } - ], - "docs": [ - " Get the current status of a node." - ], - "label": "node_get", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 72 - }, - "selector": "0x847f3997" - }, - { - "args": [ - { - "label": "pubkey", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Get the current status of a node by a public key." - ], - "label": "node_get_by_pubkey", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 72 - }, - "selector": "0x7f6c82d4" - }, - { - "args": [ - { - "label": "offset", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "limit", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "filter_provider_id", - "type": { - "displayName": [ - "Option" - ], - "type": 43 - } - } - ], - "docs": [ - " Iterate through all nodes.", - "", - " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", - " The optimal `limit` depends on the size of params.", - "", - " The results can be filtered by owner. Note that paging must still be completed fully." - ], - "label": "node_list", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [], - "type": 74 - }, - "selector": "0x423286d6" - }, - { - "args": [], - "docs": [ - " Get the Fee Percentage Basis Points that will be charged by the protocol" - ], - "label": "get_fee_bp", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "u32" - ], - "type": 9 - }, - "selector": "0x0d5daf5f" - }, - { - "args": [ - { - "label": "fee_bp", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - } - ], - "docs": [ - " Return the last commit submitted by CDN node operator" - ], - "label": "set_fee_bp", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xc5e3e2ca" - }, - { - "args": [], - "docs": [ - " Return fees accumulated by the protocol" - ], - "label": "get_protocol_revenues", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Cash" - ], - "type": 19 - }, - "selector": "0x07c63885" - }, - { - "args": [ - { - "label": "amount", - "type": { - "displayName": [ - "u128" - ], - "type": 12 - } - } - ], - "docs": [ - " Pay the revenues accumulated by the protocol" - ], - "label": "protocol_withdraw_revenues", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x85c6fa6d" - }, - { - "args": [], - "docs": [ - " As user, deposit tokens on the account of the caller from the transaction value. This deposit", - " can be used to pay for the services to buckets of the account." - ], - "label": "account_deposit", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xc311af62" - }, - { - "args": [ - { - "label": "bond_amount", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - } - ], - "docs": [ - " As user, bond some amount of tokens from the withdrawable balance. These funds will be used to pay for CDN node service." - ], - "label": "account_bond", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xe9fad0bf" - }, - { - "args": [ - { - "label": "amount_to_unbond", - "type": { - "displayName": [ - "Cash" - ], - "type": 19 - } - } - ], - "docs": [ - " As user, unbond a specified amount of tokens. The tokens will be locked for some time, as defined by contract owner." - ], - "label": "account_unbond", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xf7ea2c67" - }, - { - "args": [], - "docs": [ - " As user, move the unbonded tokens back to withdrawable balance state.", - "", - " This can be triggered after unbonded_timestamp" - ], - "label": "account_withdraw_unbonded", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x98173716" - }, - { - "args": [ - { - "label": "account_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Get the current status of an account." - ], - "label": "account_get", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 76 - }, - "selector": "0x1d4220fa" - }, - { - "args": [], - "docs": [ - " Get the current conversion rate between the native currency and an external currency (USD)." - ], - "label": "account_get_usd_per_cere", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Balance" - ], - "type": 12 - }, - "selector": "0xe4a4652a" - }, - { - "args": [ - { - "label": "usd_per_cere", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - } - ], - "docs": [ - " As price oracle, set the current conversion rate between the native currency and an external currency (USD).", - "", - " This requires the permission SetExchangeRate or SuperAdmin." - ], - "label": "account_set_usd_per_cere", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0x48d45ee8" - }, - { - "args": [ - { - "label": "grantee", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "label": "permission", - "type": { - "displayName": [ - "Permission" - ], - "type": 77 - } - } - ], - "docs": [ - " Check whether the given account has the given permission currently,", - " or the SuperAdmin permission." - ], - "label": "has_permission", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "bool" - ], - "type": 3 - }, - "selector": "0xe0942492" - }, - { - "args": [ - { - "label": "grantee", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "label": "permission", - "type": { - "displayName": [ - "Permission" - ], - "type": 77 - } - } - ], - "docs": [ - " As SuperAdmin, grant any permission to any account." - ], - "label": "admin_grant_permission", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0xbe41ea55" - }, - { - "args": [ - { - "label": "grantee", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "label": "permission", - "type": { - "displayName": [ - "Permission" - ], - "type": 77 - } - } - ], - "docs": [ - " As SuperAdmin, revoke any permission to any account." - ], - "label": "admin_revoke_permission", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0x6b150666" - }, - { - "args": [ - { - "label": "amount", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - } - ], - "docs": [ - " As SuperAdmin, withdraw the funds held in custody in this contract.", - "", - " This is a temporary measure to allow migrating the funds to a new version of the contract." - ], - "label": "admin_withdraw", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0x2f6e0868" - }, - { - "args": [ - { - "label": "config", - "type": { - "displayName": [ - "FeeConfig" - ], - "type": 78 - } - } - ], - "docs": [ - " As SuperAdmin, set the network and cluster fee configuration." - ], - "label": "admin_set_fee_config", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0x00d441e7" - }, - { - "args": [], - "docs": [ - " Get all Account IDs stored in the SC" - ], - "label": "get_accounts", - "mutates": false, - "payable": true, - "returnType": { - "displayName": [ - "Vec" - ], - "type": 14 - }, - "selector": "0xef03ead7" - } - ] - }, - "storage": { - "struct": { - "fields": [ - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0000000000000000000000000000000000000000000000000000000000000000", - "ty": 0 - } - }, - "name": null - } - ] - } - }, - "name": "perms" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0100000000000000000000000000000000000000000000000000000000000000", - "ty": 6 - } - }, - "name": null - } - ] - } - }, - "name": "buckets" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0200000000000000000000000000000000000000000000000000000000000000", - "ty": 13 - } - }, - "name": "writers" - }, - { - "layout": { - "cell": { - "key": "0x0300000000000000000000000000000000000000000000000000000000000000", - "ty": 13 - } - }, - "name": "readers" - } - ] - } - }, - "name": "buckets_perms" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0400000000000000000000000000000000000000000000000000000000000000", - "ty": 15 - } - }, - "name": null - } - ] - } - }, - "name": "bucket_params" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0500000000000000000000000000000000000000000000000000000000000000", - "ty": 17 - } - }, - "name": null - } - ] - } - }, - "name": "clusters" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0600000000000000000000000000000000000000000000000000000000000000", - "ty": 24 - } - }, - "name": null - } - ] - } - }, - "name": "cdn_clusters" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0700000000000000000000000000000000000000000000000000000000000000", - "ty": 15 - } - }, - "name": null - } - ] - } - }, - "name": "cluster_params" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0800000000000000000000000000000000000000000000000000000000000000", - "ty": 26 - } - }, - "name": null - } - ] - } - }, - "name": "cdn_nodes" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0900000000000000000000000000000000000000000000000000000000000000", - "ty": 15 - } - }, - "name": null - } - ] - } - }, - "name": "cdn_node_params" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0a00000000000000000000000000000000000000000000000000000000000000", - "ty": 28 - } - }, - "name": "account_node" - }, - { - "layout": { - "cell": { - "key": "0x0b00000000000000000000000000000000000000000000000000000000000000", - "ty": 29 - } - }, - "name": "nodes" - } - ] - } - }, - "name": "nodes" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0c00000000000000000000000000000000000000000000000000000000000000", - "ty": 15 - } - }, - "name": null - } - ] - } - }, - "name": "node_params" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0d00000000000000000000000000000000000000000000000000000000000000", - "ty": 32 - } - }, - "name": null - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0e00000000000000000000000000000000000000000000000000000000000000", - "ty": 12 - } - }, - "name": null - } - ] - } - }, - "name": null - }, - { - "layout": { - "cell": { - "key": "0x0f00000000000000000000000000000000000000000000000000000000000000", - "ty": 14 - } - }, - "name": null - } - ] - } - }, - "name": "accounts" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x1000000000000000000000000000000000000000000000000000000000000000", - "ty": 12 - } - }, - "name": "network_fee_bp" - }, - { - "layout": { - "cell": { - "key": "0x1100000000000000000000000000000000000000000000000000000000000000", - "ty": 8 - } - }, - "name": "network_fee_destination" - }, - { - "layout": { - "cell": { - "key": "0x1200000000000000000000000000000000000000000000000000000000000000", - "ty": 12 - } - }, - "name": "cluster_management_fee_bp" - } - ] - } - }, - "name": null - } - ] - } - }, - "name": "network_fee" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x1300000000000000000000000000000000000000000000000000000000000000", - "ty": 8 - } - }, - "name": "operator_id" - }, - { - "layout": { - "cell": { - "key": "0x1400000000000000000000000000000000000000000000000000000000000000", - "ty": 34 - } - }, - "name": "commits" - }, - { - "layout": { - "cell": { - "key": "0x1500000000000000000000000000000000000000000000000000000000000000", - "ty": 39 - } - }, - "name": "validated_commits" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x1600000000000000000000000000000000000000000000000000000000000000", - "ty": 23 - } - }, - "name": "start" - }, - { - "layout": { - "cell": { - "key": "0x1700000000000000000000000000000000000000000000000000000000000000", - "ty": 23 - } - }, - "name": "interval" - }, - { - "layout": { - "cell": { - "key": "0x1800000000000000000000000000000000000000000000000000000000000000", - "ty": 23 - } - }, - "name": "commit_duration" - }, - { - "layout": { - "cell": { - "key": "0x1900000000000000000000000000000000000000000000000000000000000000", - "ty": 23 - } - }, - "name": "validation_duration" - } - ] - } - }, - "name": "era_settings" - } - ] - } - }, - "name": "committer_store" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x1a00000000000000000000000000000000000000000000000000000000000000", - "ty": 8 - } - }, - "name": "admin" - }, - { - "layout": { - "cell": { - "key": "0x1b00000000000000000000000000000000000000000000000000000000000000", - "ty": 9 - } - }, - "name": "fee_bp" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x1c00000000000000000000000000000000000000000000000000000000000000", - "ty": 12 - } - }, - "name": null - } - ] - } - }, - "name": "revenues" - } - ] - } - }, - "name": "protocol_store" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x1d00000000000000000000000000000000000000000000000000000000000000", - "ty": 41 - } - }, - "name": null - } - ] - } - }, - "name": "topology_store" - } - ] - } - }, - "types": [ - { - "id": 0, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 4, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 1 - }, - { - "name": "V", - "type": 3 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 1, - "type": { - "def": { - "sequence": { - "type": 2 - } - } - } - }, - { - "id": 2, - "type": { - "def": { - "primitive": "u8" - } - } - }, - { - "id": 3, - "type": { - "def": { - "primitive": "bool" - } - } - }, - { - "id": 4, - "type": { - "def": { - "composite": { - "fields": [ - { - "type": 5, - "typeName": "[u8; 32]" - } - ] - } - }, - "path": [ - "ink_primitives", - "Key" - ] - } - }, - { - "id": 5, - "type": { - "def": { - "array": { - "len": 32, - "type": 2 - } - } - } - }, - { - "id": 6, - "type": { - "def": { - "sequence": { - "type": 7 - } - } - } - }, - { - "id": 7, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "owner_id", - "type": 8, - "typeName": "AccountId" - }, - { - "name": "cluster_id", - "type": 9, - "typeName": "ClusterId" - }, - { - "name": "flow", - "type": 10, - "typeName": "Flow" - }, - { - "name": "resource_reserved", - "type": 9, - "typeName": "Resource" - }, - { - "name": "public_availability", - "type": 3, - "typeName": "bool" - }, - { - "name": "resource_consumption_cap", - "type": 9, - "typeName": "Resource" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "bucket", - "entity", - "Bucket" - ] - } - }, - { - "id": 8, - "type": { - "def": { - "composite": { - "fields": [ - { - "type": 5, - "typeName": "[u8; 32]" - } - ] - } - }, - "path": [ - "ink_env", - "types", - "AccountId" - ] - } - }, - { - "id": 9, - "type": { - "def": { - "primitive": "u32" - } - } - }, - { - "id": 10, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "from", - "type": 8, - "typeName": "AccountId" - }, - { - "name": "schedule", - "type": 11, - "typeName": "Schedule" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "flow", - "Flow" - ] - } - }, - { - "id": 11, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "rate", - "type": 12, - "typeName": "Balance" - }, - { - "name": "offset", - "type": 12, - "typeName": "Balance" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "schedule", - "Schedule" - ] - } - }, - { - "id": 12, - "type": { - "def": { - "primitive": "u128" - } - } - }, - { - "id": 13, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 4, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 9 - }, - { - "name": "V", - "type": 14 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 14, - "type": { - "def": { - "sequence": { - "type": 8 - } - } - } - }, - { - "id": 15, - "type": { - "def": { - "sequence": { - "type": 16 - } - } - } - }, - { - "id": 16, - "type": { - "def": { - "primitive": "str" - } - } - }, - { - "id": 17, - "type": { - "def": { - "sequence": { - "type": 18 - } - } - } - }, - { - "id": 18, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "manager_id", - "type": 8, - "typeName": "AccountId" - }, - { - "name": "resource_per_vnode", - "type": 9, - "typeName": "Resource" - }, - { - "name": "resource_used", - "type": 9, - "typeName": "Resource" - }, - { - "name": "revenues", - "type": 19, - "typeName": "Cash" - }, - { - "name": "node_ids", - "type": 20, - "typeName": "Vec" - }, - { - "name": "v_nodes", - "type": 21, - "typeName": "Vec>" - }, - { - "name": "total_rent", - "type": 12, - "typeName": "Balance" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cluster", - "entity", - "Cluster" - ] - } - }, - { - "id": 19, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "value", - "type": 12, - "typeName": "Balance" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cash", - "Cash" - ] - } - }, - { - "id": 20, - "type": { - "def": { - "sequence": { - "type": 9 - } - } - } - }, - { - "id": 21, - "type": { - "def": { - "sequence": { - "type": 22 - } - } - } - }, - { - "id": 22, - "type": { - "def": { - "sequence": { - "type": 23 - } - } - } - }, - { - "id": 23, - "type": { - "def": { - "primitive": "u64" - } - } - }, - { - "id": 24, - "type": { - "def": { - "sequence": { - "type": 25 - } - } - } - }, - { - "id": 25, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "manager_id", - "type": 8, - "typeName": "AccountId" - }, - { - "name": "cdn_nodes", - "type": 20, - "typeName": "Vec" - }, - { - "name": "resources_used", - "type": 9, - "typeName": "Resource" - }, - { - "name": "revenues", - "type": 19, - "typeName": "Cash" - }, - { - "name": "usd_per_gb", - "type": 12, - "typeName": "Balance" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cdn_cluster", - "entity", - "CdnCluster" - ] - } - }, - { - "id": 26, - "type": { - "def": { - "sequence": { - "type": 27 - } - } - } - }, - { - "id": 27, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "provider_id", - "type": 8, - "typeName": "ProviderId" - }, - { - "name": "undistributed_payment", - "type": 12, - "typeName": "Balance" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cdn_node", - "entity", - "CdnNode" - ] - } - }, - { - "id": 28, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 4, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 8 - }, - { - "name": "V", - "type": 9 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 29, - "type": { - "def": { - "sequence": { - "type": 30 - } - } - } - }, - { - "id": 30, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "provider_id", - "type": 8, - "typeName": "ProviderId" - }, - { - "name": "rent_per_month", - "type": 12, - "typeName": "Balance" - }, - { - "name": "free_resource", - "type": 9, - "typeName": "Resource" - }, - { - "name": "node_tag", - "type": 31, - "typeName": "NodeTag" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "node", - "entity", - "Node" - ] - } - }, - { - "id": 31, - "type": { - "def": { - "variant": { - "variants": [ - { - "index": 0, - "name": "UNKNOWN" - }, - { - "index": 1, - "name": "ACTIVE" - }, - { - "index": 2, - "name": "ADDING" - }, - { - "index": 3, - "name": "DELETING" - }, - { - "index": 4, - "name": "OFFLINE" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "node", - "entity", - "NodeTag" - ] - } - }, - { - "id": 32, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 4, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 8 - }, - { - "name": "V", - "type": 33 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 33, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "deposit", - "type": 19, - "typeName": "Cash" - }, - { - "name": "bonded", - "type": 19, - "typeName": "Cash" - }, - { - "name": "negative", - "type": 19, - "typeName": "Cash" - }, - { - "name": "unbonded_amount", - "type": 19, - "typeName": "Cash" - }, - { - "name": "unbonded_timestamp", - "type": 23, - "typeName": "u64" - }, - { - "name": "payable_schedule", - "type": 11, - "typeName": "Schedule" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "account", - "entity", - "Account" - ] - } - }, - { - "id": 34, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 4, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 8 - }, - { - "name": "V", - "type": 35 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 35, - "type": { - "def": { - "sequence": { - "type": 36 - } - } - } - }, - { - "id": 36, - "type": { - "def": { - "tuple": [ - 9, - 37 - ] - } - } - }, - { - "id": 37, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "hash", - "type": 38, - "typeName": "Hash" - }, - { - "name": "total_logs", - "type": 12, - "typeName": "u128" - }, - { - "name": "from_timestamp", - "type": 23, - "typeName": "u64" - }, - { - "name": "to_timestamp", - "type": 23, - "typeName": "u64" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "committer", - "store", - "Commit" - ] - } - }, - { - "id": 38, - "type": { - "def": { - "composite": { - "fields": [ - { - "type": 5, - "typeName": "[u8; 32]" - } - ] - } - }, - "path": [ - "ink_env", - "types", - "Hash" - ] - } - }, - { - "id": 39, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 4, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 9 - }, - { - "name": "V", - "type": 40 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 40, - "type": { - "def": { - "tuple": [ - 23, - 23 - ] - } - } - }, - { - "id": 41, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 4, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 42 - }, - { - "name": "V", - "type": 9 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 42, - "type": { - "def": { - "tuple": [ - 9, - 23 - ] - } - } - }, - { - "id": 43, - "type": { - "def": { - "variant": { - "variants": [ - { - "index": 0, - "name": "None" - }, - { - "fields": [ - { - "type": 8 - } - ], - "index": 1, - "name": "Some" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 8 - } - ], - "path": [ - "Option" - ] - } - }, - { - "id": 44, - "type": { - "def": { - "tuple": [] - } - } - }, - { - "id": 45, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 46 - } - ], - "index": 0, - "name": "Ok" - }, - { - "fields": [ - { - "type": 48 - } - ], - "index": 1, - "name": "Err" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 46 - }, - { - "name": "E", - "type": 48 - } - ], - "path": [ - "Result" - ] - } - }, - { - "id": 46, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "bucket_id", - "type": 9, - "typeName": "BucketId" - }, - { - "name": "bucket", - "type": 47, - "typeName": "BucketInStatus" - }, - { - "name": "params", - "type": 16, - "typeName": "BucketParams" - }, - { - "name": "writer_ids", - "type": 14, - "typeName": "Vec" - }, - { - "name": "reader_ids", - "type": 14, - "typeName": "Vec" - }, - { - "name": "rent_covered_until_ms", - "type": 23, - "typeName": "u64" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "bucket", - "entity", - "BucketStatus" - ] - } - }, - { - "id": 47, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "owner_id", - "type": 8, - "typeName": "AccountId" - }, - { - "name": "cluster_id", - "type": 9, - "typeName": "ClusterId" - }, - { - "name": "resource_reserved", - "type": 9, - "typeName": "Resource" - }, - { - "name": "public_availability", - "type": 3, - "typeName": "bool" - }, - { - "name": "resource_consumption_cap", - "type": 9, - "typeName": "Resource" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "bucket", - "entity", - "BucketInStatus" - ] - } - }, - { - "id": 48, - "type": { - "def": { - "variant": { - "variants": [ - { - "index": 0, - "name": "BucketDoesNotExist" - }, - { - "index": 1, - "name": "ClusterDoesNotExist" - }, - { - "index": 2, - "name": "ParamsTooBig" - }, - { - "index": 3, - "name": "VNodeDoesNotExist" - }, - { - "index": 4, - "name": "BondingPeriodNotFinished" - }, - { - "index": 5, - "name": "BucketClusterAlreadyConnected" - }, - { - "index": 6, - "name": "BucketClusterNotSetup" - }, - { - "index": 7, - "name": "NodeDoesNotExist" - }, - { - "index": 8, - "name": "NodeAlreadyExists" - }, - { - "index": 9, - "name": "FlowDoesNotExist" - }, - { - "index": 10, - "name": "AccountDoesNotExist" - }, - { - "index": 11, - "name": "ParamsDoesNotExist" - }, - { - "index": 12, - "name": "UnauthorizedProvider" - }, - { - "index": 13, - "name": "UnauthorizedOwner" - }, - { - "index": 14, - "name": "UnauthorizedClusterManager" - }, - { - "index": 15, - "name": "ClusterManagerIsNotTrusted" - }, - { - "index": 16, - "name": "TransferFailed" - }, - { - "index": 17, - "name": "InsufficientBalance" - }, - { - "index": 18, - "name": "InsufficientResources" - }, - { - "index": 19, - "name": "Unauthorized" - }, - { - "index": 20, - "name": "UnknownNode" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "Error" - ] - } - }, - { - "id": 49, - "type": { - "def": { - "tuple": [ - 50, - 9 - ] - } - } - }, - { - "id": 50, - "type": { - "def": { - "sequence": { - "type": 46 - } - } - } - }, - { - "id": 51, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 52 - } - ], - "index": 0, - "name": "Ok" - }, - { - "fields": [ - { - "type": 48 - } - ], - "index": 1, - "name": "Err" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 52 - }, - { - "name": "E", - "type": 48 - } - ], - "path": [ - "Result" - ] - } - }, - { - "id": 52, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "cluster_id", - "type": 9, - "typeName": "ClusterId" - }, - { - "name": "cluster", - "type": 18, - "typeName": "Cluster" - }, - { - "name": "params", - "type": 16, - "typeName": "Params" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cluster", - "entity", - "ClusterStatus" - ] - } - }, - { - "id": 53, - "type": { - "def": { - "tuple": [ - 54, - 9 - ] - } - } - }, - { - "id": 54, - "type": { - "def": { - "sequence": { - "type": 52 - } - } - } - }, - { - "id": 55, - "type": { - "def": { - "sequence": { - "type": 56 - } - } - } - }, - { - "id": 56, - "type": { - "def": { - "tuple": [ - 8, - 12 - ] - } - } - }, - { - "id": 57, - "type": { - "def": { - "sequence": { - "type": 58 - } - } - } - }, - { - "id": 58, - "type": { - "def": { - "tuple": [ - 9, - 12 - ] - } - } - }, - { - "id": 59, - "type": { - "def": { - "sequence": { - "type": 60 - } - } - } - }, - { - "id": 60, - "type": { - "def": { - "tuple": [ - 9, - 9 - ] - } - } - }, - { - "id": 61, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 62 - } - ], - "index": 0, - "name": "Ok" - }, - { - "fields": [ - { - "type": 48 - } - ], - "index": 1, - "name": "Err" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 62 - }, - { - "name": "E", - "type": 48 - } - ], - "path": [ - "Result" - ] - } - }, - { - "id": 62, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "cluster_id", - "type": 9, - "typeName": "ClusterId" - }, - { - "name": "cluster", - "type": 25, - "typeName": "CdnCluster" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cdn_cluster", - "entity", - "CdnClusterStatus" - ] - } - }, - { - "id": 63, - "type": { - "def": { - "tuple": [ - 64, - 9 - ] - } - } - }, - { - "id": 64, - "type": { - "def": { - "sequence": { - "type": 62 - } - } - } - }, - { - "id": 65, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "start", - "type": 23, - "typeName": "u64" - }, - { - "name": "interval", - "type": 23, - "typeName": "u64" - }, - { - "name": "commit_duration", - "type": 23, - "typeName": "u64" - }, - { - "name": "validation_duration", - "type": 23, - "typeName": "u64" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "committer", - "store", - "EraConfig" - ] - } - }, - { - "id": 66, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "current_era", - "type": 23, - "typeName": "u64" - }, - { - "name": "current_phase", - "type": 67, - "typeName": "Phase" - }, - { - "name": "previous_era", - "type": 23, - "typeName": "u64" - }, - { - "name": "prev_era_from_timestamp", - "type": 23, - "typeName": "u64" - }, - { - "name": "prev_era_to_timestamp", - "type": 23, - "typeName": "u64" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "committer", - "store", - "EraStatus" - ] - } - }, - { - "id": 67, - "type": { - "def": { - "variant": { - "variants": [ - { - "index": 0, - "name": "Commit" - }, - { - "index": 1, - "name": "Valiadation" - }, - { - "index": 2, - "name": "Payout" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "committer", - "store", - "Phase" - ] - } - }, - { - "id": 68, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 69 - } - ], - "index": 0, - "name": "Ok" - }, - { - "fields": [ - { - "type": 48 - } - ], - "index": 1, - "name": "Err" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 69 - }, - { - "name": "E", - "type": 48 - } - ], - "path": [ - "Result" - ] - } - }, - { - "id": 69, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "node_id", - "type": 9, - "typeName": "NodeId" - }, - { - "name": "node", - "type": 27, - "typeName": "CdnNode" - }, - { - "name": "params", - "type": 16, - "typeName": "Params" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cdn_node", - "entity", - "CdnNodeStatus" - ] - } - }, - { - "id": 70, - "type": { - "def": { - "tuple": [ - 71, - 9 - ] - } - } - }, - { - "id": 71, - "type": { - "def": { - "sequence": { - "type": 69 - } - } - } - }, - { - "id": 72, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 73 - } - ], - "index": 0, - "name": "Ok" - }, - { - "fields": [ - { - "type": 48 - } - ], - "index": 1, - "name": "Err" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 73 - }, - { - "name": "E", - "type": 48 - } - ], - "path": [ - "Result" - ] - } - }, - { - "id": 73, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "node_id", - "type": 9, - "typeName": "NodeId" - }, - { - "name": "node", - "type": 30, - "typeName": "Node" - }, - { - "name": "params", - "type": 16, - "typeName": "Params" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "node", - "entity", - "NodeStatus" - ] - } - }, - { - "id": 74, - "type": { - "def": { - "tuple": [ - 75, - 9 - ] - } - } - }, - { - "id": 75, - "type": { - "def": { - "sequence": { - "type": 73 - } - } - } - }, - { - "id": 76, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 33 - } - ], - "index": 0, - "name": "Ok" - }, - { - "fields": [ - { - "type": 48 - } - ], - "index": 1, - "name": "Err" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 33 - }, - { - "name": "E", - "type": 48 - } - ], - "path": [ - "Result" - ] - } - }, - { - "id": 77, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 8, - "typeName": "AccountId" - } - ], - "index": 0, - "name": "ManagerTrustedBy" - }, - { - "index": 1, - "name": "SetExchangeRate" - }, - { - "index": 2, - "name": "SuperAdmin" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "perm", - "entity", - "Permission" - ] - } - }, - { - "id": 78, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "network_fee_bp", - "type": 12, - "typeName": "BasisPoints" - }, - { - "name": "network_fee_destination", - "type": 8, - "typeName": "AccountId" - }, - { - "name": "cluster_management_fee_bp", - "type": 12, - "typeName": "BasisPoints" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "network_fee", - "FeeConfig" - ] - } - } - ] - } -} \ No newline at end of file diff --git a/bucket/scripts/package-lock.json b/bucket/scripts/package-lock.json deleted file mode 100644 index 0411d6de..00000000 --- a/bucket/scripts/package-lock.json +++ /dev/null @@ -1,789 +0,0 @@ -{ - "name": "scripts", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "dependencies": { - "@polkadot/api": "^10.9.1", - "@polkadot/api-contract": "^10.9.1", - "@polkadot/util-crypto": "^12.3.2" - } - }, - "node_modules/@noble/curves": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", - "dependencies": { - "@noble/hashes": "1.3.1" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@polkadot/api": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-10.9.1.tgz", - "integrity": "sha512-ND/2UqZBWvtt4PfV03OStTKg0mxmPk4UpMAgJKutdgsz/wP9CYJ1KbjwFgPNekL9JnzbKQsWyQNPVrcw7kQk8A==", - "dependencies": { - "@polkadot/api-augment": "10.9.1", - "@polkadot/api-base": "10.9.1", - "@polkadot/api-derive": "10.9.1", - "@polkadot/keyring": "^12.3.1", - "@polkadot/rpc-augment": "10.9.1", - "@polkadot/rpc-core": "10.9.1", - "@polkadot/rpc-provider": "10.9.1", - "@polkadot/types": "10.9.1", - "@polkadot/types-augment": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/types-create": "10.9.1", - "@polkadot/types-known": "10.9.1", - "@polkadot/util": "^12.3.1", - "@polkadot/util-crypto": "^12.3.1", - "eventemitter3": "^5.0.1", - "rxjs": "^7.8.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/api-augment": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-10.9.1.tgz", - "integrity": "sha512-kRZZvCFVcN4hAH4dJ+Qzfdy27/4EEq3oLDf3ihj0LTVrAezSWcKPGE3EVFy+Mn6Lo4SUc7RVyoKvIUhSk2l4Dg==", - "dependencies": { - "@polkadot/api-base": "10.9.1", - "@polkadot/rpc-augment": "10.9.1", - "@polkadot/types": "10.9.1", - "@polkadot/types-augment": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/util": "^12.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/api-base": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-10.9.1.tgz", - "integrity": "sha512-Q3m2KzlceMK2kX8bhnUZWk3RT6emmijeeFZZQgCePpEcrSeNjnqG4qjuTPgkveaOkUT8MAoDc5Avuzcc2jlW9g==", - "dependencies": { - "@polkadot/rpc-core": "10.9.1", - "@polkadot/types": "10.9.1", - "@polkadot/util": "^12.3.1", - "rxjs": "^7.8.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/api-contract": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-contract/-/api-contract-10.9.1.tgz", - "integrity": "sha512-BJjFYSFtsUlClC3mgvPNQ5h/7LZd5gVfexwl+mDgLd/6SN4dUBQjIXhlIL5a1cGYjq3EROuu7t0agG2DIaiZMQ==", - "dependencies": { - "@polkadot/api": "10.9.1", - "@polkadot/api-augment": "10.9.1", - "@polkadot/types": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/types-create": "10.9.1", - "@polkadot/util": "^12.3.1", - "@polkadot/util-crypto": "^12.3.1", - "rxjs": "^7.8.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/api-derive": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-10.9.1.tgz", - "integrity": "sha512-mRud1UZCFIc4Z63qAoGSIHh/foyUYADfy1RQYCmPpeFKfIdCIrHpd7xFdJXTOMYOS0BwlM6u4qli/ZT4XigezQ==", - "dependencies": { - "@polkadot/api": "10.9.1", - "@polkadot/api-augment": "10.9.1", - "@polkadot/api-base": "10.9.1", - "@polkadot/rpc-core": "10.9.1", - "@polkadot/types": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/util": "^12.3.1", - "@polkadot/util-crypto": "^12.3.1", - "rxjs": "^7.8.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/keyring": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-12.3.2.tgz", - "integrity": "sha512-NTdtDeI0DP9l/45hXynNABeP5VB8piw5YR+CbUxK2e36xpJWVXwbcOepzslg5ghE9rs8UKJb30Z/HqTU4sBY0Q==", - "dependencies": { - "@polkadot/util": "12.3.2", - "@polkadot/util-crypto": "12.3.2", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "12.3.2", - "@polkadot/util-crypto": "12.3.2" - } - }, - "node_modules/@polkadot/networks": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-12.3.2.tgz", - "integrity": "sha512-uCkyybKoeEm1daKr0uT/9oNDHDDzCy2/ZdVl346hQqfdR1Ct3BaxMjxqvdmb5N8aCw0cBWSfgsxAYtw8ESmllQ==", - "dependencies": { - "@polkadot/util": "12.3.2", - "@substrate/ss58-registry": "^1.40.0", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/rpc-augment": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-10.9.1.tgz", - "integrity": "sha512-MaLHkNlyqN20ZRYr6uNd1BZr1OsrnX9qLAmsl0mcrri1vPGRH6VHjfFH1RBLkikpWD82v17g0l2hLwdV1ZHMcw==", - "dependencies": { - "@polkadot/rpc-core": "10.9.1", - "@polkadot/types": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/util": "^12.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/rpc-core": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-10.9.1.tgz", - "integrity": "sha512-ZtA8B8SfXSAwVkBlCcKRHw0eSM7ec/sbiNOM5GasXPeRujUgT7lOwSH2GbUZSqe9RfRDMp6DvO9c2JoGc3LLWw==", - "dependencies": { - "@polkadot/rpc-augment": "10.9.1", - "@polkadot/rpc-provider": "10.9.1", - "@polkadot/types": "10.9.1", - "@polkadot/util": "^12.3.1", - "rxjs": "^7.8.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/rpc-provider": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-10.9.1.tgz", - "integrity": "sha512-4QzT2QzD+320+eT6b79sGAA85Tt3Bb8fQvse4r5Mom2iiBd2SO81vOhxSAOaIe4GUsw25VzFJmsbe7+OObItdg==", - "dependencies": { - "@polkadot/keyring": "^12.3.1", - "@polkadot/types": "10.9.1", - "@polkadot/types-support": "10.9.1", - "@polkadot/util": "^12.3.1", - "@polkadot/util-crypto": "^12.3.1", - "@polkadot/x-fetch": "^12.3.1", - "@polkadot/x-global": "^12.3.1", - "@polkadot/x-ws": "^12.3.1", - "eventemitter3": "^5.0.1", - "mock-socket": "^9.2.1", - "nock": "^13.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - }, - "optionalDependencies": { - "@substrate/connect": "0.7.26" - } - }, - "node_modules/@polkadot/types": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.9.1.tgz", - "integrity": "sha512-AG33i2ZGGfq7u+5rkAdGrXAQHHl844/Yv+junH5ZzX69xiCoWO1bH/yzDUNBdpki2GlACWvF9nLYh3F2tVF93w==", - "dependencies": { - "@polkadot/keyring": "^12.3.1", - "@polkadot/types-augment": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/types-create": "10.9.1", - "@polkadot/util": "^12.3.1", - "@polkadot/util-crypto": "^12.3.1", - "rxjs": "^7.8.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/types-augment": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-10.9.1.tgz", - "integrity": "sha512-OY9/jTMFRFqYdkUnfcGwqMLC64A0Q25bjvCuVQCVjsPFKE3wl0Kt5rNT01eV2UmLXrR6fY0xWbR2w80bLA7CIQ==", - "dependencies": { - "@polkadot/types": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/util": "^12.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/types-codec": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-10.9.1.tgz", - "integrity": "sha512-mJ5OegKGraY1FLvEa8FopRCr3pQrhDkcn5RNOjmgJQozENVeRaxhk0NwxYz7IojFvSDnKnc6lNQfKaaSe5pLHg==", - "dependencies": { - "@polkadot/util": "^12.3.1", - "@polkadot/x-bigint": "^12.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/types-create": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-10.9.1.tgz", - "integrity": "sha512-OVz50MGTTuiuVnRP/zAx4CTuLioc0hsiwNwqN2lNhmIJGtnQ4Vy/7mQRsIWehiYz6g0Vzzm5B3qWkTXO1NSN5w==", - "dependencies": { - "@polkadot/types-codec": "10.9.1", - "@polkadot/util": "^12.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/types-known": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-10.9.1.tgz", - "integrity": "sha512-zCMVWc4pJtkbMFPu72bD4IhvV/gkHXPX3C5uu92WdmCfnn0vEIEsMKWlVXVVvQQZKAqvs/awpqIfrUtEViOGEA==", - "dependencies": { - "@polkadot/networks": "^12.3.1", - "@polkadot/types": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/types-create": "10.9.1", - "@polkadot/util": "^12.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/types-support": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-10.9.1.tgz", - "integrity": "sha512-XsieuLDsszvMZQlleacQBfx07i/JkwQV/UxH9q8Hz7Okmaz9pEVEW1h3ka2/cPuC7a4l32JhaORBUYshBZNdJg==", - "dependencies": { - "@polkadot/util": "^12.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/util": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-12.3.2.tgz", - "integrity": "sha512-y/JShcGyOamCUiSIg++XZuLHt1ktSKBaSH2K5Nw5NXlgP0+7am+GZzqPB8fQ4qhYLruEOv+YRiz0GC1Zr9S+wg==", - "dependencies": { - "@polkadot/x-bigint": "12.3.2", - "@polkadot/x-global": "12.3.2", - "@polkadot/x-textdecoder": "12.3.2", - "@polkadot/x-textencoder": "12.3.2", - "@types/bn.js": "^5.1.1", - "bn.js": "^5.2.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/util-crypto": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-12.3.2.tgz", - "integrity": "sha512-pTpx+YxolY0BDT4RcGmgeKbHHD/dI6Ll9xRsqmVdIjpcVVY20uDNTyXs81ZNtfKgyod1y9JQkfNv2Dz9iEpTkQ==", - "dependencies": { - "@noble/curves": "1.1.0", - "@noble/hashes": "1.3.1", - "@polkadot/networks": "12.3.2", - "@polkadot/util": "12.3.2", - "@polkadot/wasm-crypto": "^7.2.1", - "@polkadot/wasm-util": "^7.2.1", - "@polkadot/x-bigint": "12.3.2", - "@polkadot/x-randomvalues": "12.3.2", - "@scure/base": "1.1.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "12.3.2" - } - }, - "node_modules/@polkadot/wasm-bridge": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.2.1.tgz", - "integrity": "sha512-uV/LHREDBGBbHrrv7HTki+Klw0PYZzFomagFWII4lp6Toj/VCvRh5WMzooVC+g/XsBGosAwrvBhoModabyHx+A==", - "dependencies": { - "@polkadot/wasm-util": "7.2.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "*", - "@polkadot/x-randomvalues": "*" - } - }, - "node_modules/@polkadot/wasm-crypto": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-7.2.1.tgz", - "integrity": "sha512-SA2+33S9TAwGhniKgztVN6pxUKpGfN4Tre/eUZGUfpgRkT92wIUT2GpGWQE+fCCqGQgADrNiBcwt6XwdPqMQ4Q==", - "dependencies": { - "@polkadot/wasm-bridge": "7.2.1", - "@polkadot/wasm-crypto-asmjs": "7.2.1", - "@polkadot/wasm-crypto-init": "7.2.1", - "@polkadot/wasm-crypto-wasm": "7.2.1", - "@polkadot/wasm-util": "7.2.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "*", - "@polkadot/x-randomvalues": "*" - } - }, - "node_modules/@polkadot/wasm-crypto-asmjs": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.2.1.tgz", - "integrity": "sha512-z/d21bmxyVfkzGsKef/FWswKX02x5lK97f4NPBZ9XBeiFkmzlXhdSnu58/+b1sKsRAGdW/Rn/rTNRDhW0GqCAg==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "*" - } - }, - "node_modules/@polkadot/wasm-crypto-init": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.2.1.tgz", - "integrity": "sha512-GcEXtwN9LcSf32V9zSaYjHImFw16hCyo2Xzg4GLLDPPeaAAfbFr2oQMgwyDbvBrBjLKHVHjsPZyGhXae831amw==", - "dependencies": { - "@polkadot/wasm-bridge": "7.2.1", - "@polkadot/wasm-crypto-asmjs": "7.2.1", - "@polkadot/wasm-crypto-wasm": "7.2.1", - "@polkadot/wasm-util": "7.2.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "*", - "@polkadot/x-randomvalues": "*" - } - }, - "node_modules/@polkadot/wasm-crypto-wasm": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.2.1.tgz", - "integrity": "sha512-DqyXE4rSD0CVlLIw88B58+HHNyrvm+JAnYyuEDYZwCvzUWOCNos/DDg9wi/K39VAIsCCKDmwKqkkfIofuOj/lA==", - "dependencies": { - "@polkadot/wasm-util": "7.2.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "*" - } - }, - "node_modules/@polkadot/wasm-util": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.2.1.tgz", - "integrity": "sha512-FBSn/3aYJzhN0sYAYhHB8y9JL8mVgxLy4M1kUXYbyo+8GLRQEN5rns8Vcb8TAlIzBWgVTOOptYBvxo0oj0h7Og==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "*" - } - }, - "node_modules/@polkadot/x-bigint": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-12.3.2.tgz", - "integrity": "sha512-JLqLgfGXe/x+hZJETd5ZqfpVsbwyMsH5Nn1Q20ineMMjXN/ig+kVR8Mc15LXBMuw4g7LldFW6UUrotWnuMI8Yw==", - "dependencies": { - "@polkadot/x-global": "12.3.2", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/x-fetch": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-12.3.2.tgz", - "integrity": "sha512-3IEuZ5S+RI/t33NsdPLIIa5COfDCfpUW2sbaByEczn75aD1jLqJZSEDwiBniJ2osyNd4uUxBf6e5jw7LAZeZJg==", - "dependencies": { - "@polkadot/x-global": "12.3.2", - "node-fetch": "^3.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/x-global": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-12.3.2.tgz", - "integrity": "sha512-yVZq6oIegjlyh5rUZiTklgu+fL+W/DG1ypEa02683tUCB3avV5cA3PAHKptMSlb6FpweHu37lKKrqfAWrraDxg==", - "dependencies": { - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/x-randomvalues": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-12.3.2.tgz", - "integrity": "sha512-ywjIs8CWpvOGmq+3cGCNPOHxAjPHdBUiXyDccftx5BRVdmtbt36gK/V84bKr6Xs73FGu0jprUAOSRRsLZX/3dg==", - "dependencies": { - "@polkadot/x-global": "12.3.2", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "12.3.2", - "@polkadot/wasm-util": "*" - } - }, - "node_modules/@polkadot/x-textdecoder": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-12.3.2.tgz", - "integrity": "sha512-lY5bfA5xArJRWEJlYOlQQMJeTjWD8s0yMhchirVgf5xj8Id9vPGeUoneH+VFDEwgXxrqBvDFJ4smN4T/r6a/fg==", - "dependencies": { - "@polkadot/x-global": "12.3.2", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/x-textencoder": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-12.3.2.tgz", - "integrity": "sha512-iP3qEBiHzBckQ9zeY7ZHRWuu7mCEg5SMpOugs6UODRk8sx6KHzGQYlghBbWLit0uppPDVE0ifEwZ2n73djJHWQ==", - "dependencies": { - "@polkadot/x-global": "12.3.2", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/x-ws": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-12.3.2.tgz", - "integrity": "sha512-yM9Z64pLNlHpJE43+Xtr+iUXmYpFFY5u5hrke2PJt13O48H8f9Vb9cRaIh94appLyICoS0aekGhDkGH+MCspBA==", - "dependencies": { - "@polkadot/x-global": "12.3.2", - "tslib": "^2.5.3", - "ws": "^8.13.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@scure/base": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", - "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@substrate/connect": { - "version": "0.7.26", - "resolved": "https://registry.npmjs.org/@substrate/connect/-/connect-0.7.26.tgz", - "integrity": "sha512-uuGSiroGuKWj1+38n1kY5HReer5iL9bRwPCzuoLtqAOmI1fGI0hsSI2LlNQMAbfRgr7VRHXOk5MTuQf5ulsFRw==", - "optional": true, - "dependencies": { - "@substrate/connect-extension-protocol": "^1.0.1", - "eventemitter3": "^4.0.7", - "smoldot": "1.0.4" - } - }, - "node_modules/@substrate/connect-extension-protocol": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-1.0.1.tgz", - "integrity": "sha512-161JhCC1csjH3GE5mPLEd7HbWtwNSPJBg3p1Ksz9SFlTzj/bgEwudiRN2y5i0MoLGCIJRYKyKGMxVnd29PzNjg==", - "optional": true - }, - "node_modules/@substrate/connect/node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "optional": true - }, - "node_modules/@substrate/ss58-registry": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.40.0.tgz", - "integrity": "sha512-QuU2nBql3J4KCnOWtWDw4n1K4JU0T79j54ZZvm/9nhsX6AIar13FyhsaBfs6QkJ2ixTQAnd7TocJIoJRWbqMZA==" - }, - "node_modules/@types/bn.js": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz", - "integrity": "sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz", - "integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==" - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/mock-socket": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.2.1.tgz", - "integrity": "sha512-aw9F9T9G2zpGipLLhSNh6ZpgUyUl4frcVmRN08uE1NWPWg43Wx6+sGPDbQ7E5iFZZDJW5b5bypMeAEHqTbIFag==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/nock": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.1.tgz", - "integrity": "sha512-vHnopocZuI93p2ccivFyGuUfzjq2fxNyNurp7816mlT5V5HF4SzXu8lvLrVzBbNqzs+ODooZ6OksuSUNM7Njkw==", - "dependencies": { - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.21", - "propagate": "^2.0.0" - }, - "engines": { - "node": ">= 10.13" - } - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", - "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/pako": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", - "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", - "optional": true - }, - "node_modules/propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/smoldot": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-1.0.4.tgz", - "integrity": "sha512-N3TazI1C4GGrseFH/piWyZCCCRJTRx2QhDfrUKRT4SzILlW5m8ayZ3QTKICcz1C/536T9cbHHJyP7afxI6Mi1A==", - "optional": true, - "dependencies": { - "pako": "^2.0.4", - "ws": "^8.8.1" - } - }, - "node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" - }, - "node_modules/web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - } - } -} diff --git a/bucket/scripts/package.json b/bucket/scripts/package.json deleted file mode 100644 index bc305466..00000000 --- a/bucket/scripts/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "module", - "dependencies": { - "@polkadot/api": "^10.9.1", - "@polkadot/api-contract": "^10.9.1", - "@polkadot/util-crypto": "^12.3.2" - } -} diff --git a/scripts/.gitignore b/scripts/.gitignore index 99600f94..87b5d6ff 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -1,2 +1,3 @@ node_modules -yarn-error.log \ No newline at end of file +yarn-error.log +secrets.txt \ No newline at end of file diff --git a/bucket/scripts/config.js b/scripts/ddc-setup/ddcConfig.js similarity index 99% rename from bucket/scripts/config.js rename to scripts/ddc-setup/ddcConfig.js index 0323cfe1..0517238f 100644 --- a/bucket/scripts/config.js +++ b/scripts/ddc-setup/ddcConfig.js @@ -1,6 +1,6 @@ const GEN = 0x10000000000000000n; // UINT64_MAX -export const config = { +module.exports = { devnet: { ws_provider: "wss://archive.devnet.cere.network/ws", contract_address: "6SfBsKbfPUTN35GCcqAHSMY4MemedK2A73VeJ34Z2FV6PB4r", diff --git a/scripts/ddc-setup/ddcSetup.js b/scripts/ddc-setup/ddcSetup.js new file mode 100644 index 00000000..eb3e99e3 --- /dev/null +++ b/scripts/ddc-setup/ddcSetup.js @@ -0,0 +1,147 @@ +const fs = require("fs"); +const { + connect, + accountFromUri, + sendTx, + getContract, + CERE, + MGAS, + ddcBucket, + randomAccount, + deploymentRegistry, + config +} = require("../sdk/src"); +const ddcConfig = require('./ddcConfig.js'); +const log = console.log; + +const DDC_BUCKET_CONTRACT_NAME = config.DDC_BUCKET_CONTRACT_NAME; +const INIT_ENV = process.env.INIT_ENV; +const SUPERADMIN_MNEMONIC = process.env.SUPERADMIN; + + +const ddcEnvConfig = ddcConfig[INIT_ENV]; +if (ddcEnvConfig === undefined) { + console.error("Please provide INIT_ENV as one of ", Object.keys(ddcConfig)); + process.exit(-1); +} +console.log(ddcEnvConfig); + +deploymentRegistry.initContract( + DDC_BUCKET_CONTRACT_NAME, + INIT_ENV, + ddcEnvConfig.contract_address +); + + +async function main() { + const {api, chainName, getExplorerUrl} = await connect(ddcEnvConfig.ws_provider); + log("Connected to blockchain:", chainName); + + const sadmin = accountFromUri(SUPERADMIN_MNEMONIC); + console.log(`Superadmin: ${sadmin.address}`); + + const bucketContract = getContract(DDC_BUCKET_CONTRACT_NAME, INIT_ENV, api); + log("Using bucket contract", DDC_BUCKET_CONTRACT_NAME, "at", bucketContract.address.toString()); + + const txOptions = { + storageDepositLimit: null, + gasLimit: 100_000_000_000n, + }; + + { + log("1. accountSetUsdPerCere"); + const tx = bucketContract.tx.accountSetUsdPerCere( + txOptions, + 1000n * CERE + ); + + const result = await sendTx(sadmin, tx); + log(getExplorerUrl(result), "\n"); + } + + { + log("2. grantTrustedManagerPermission"); + const tx = bucketContract.tx.grantTrustedManagerPermission( + txOptions, + sadmin.address + ); + const result = await sendTx(sadmin, tx); + log(getExplorerUrl(result), "\n"); + } + + const cdnNodesKeys = [] + { + console.log("3. cdnNodeCreate"); + for (let i = 0; i < ddcEnvConfig.cdn_node_params.length; i++) { + const cdnNodeKey = ddcEnvConfig.cdn_node_params[i].publicKey; + cdnNodesKeys.push(cdnNodeKey); + + const tx = bucketContract.tx.cdnNodeCreate( + txOptions, + cdnNodeKey, + JSON.stringify(ddcEnvConfig.cdn_node_params[i]) + ); + + const result = await sendTx(sadmin, tx); + log(getExplorerUrl(result), "\n"); + } + } + + const storageNodesKeys = [] + { + console.log("4. nodeCreate"); + for (let i = 0; i < ddcEnvConfig.storage_node_params.length; i++) { + const param = JSON.stringify(ddcEnvConfig.storage_node_params[i]); + const user = randomAccount(); + + fs.appendFileSync('secrets.txt', `${user.address}: ${user.mnemonic} -- ${INIT_ENV} storage ${i}\n`); + console.log(` node ${i}: address ${user.address}, param ${param}`); + + const storageNodeKey = user.address; + storageNodesKeys.push(storageNodeKey); + + const tx = bucketContract.tx.nodeCreate( + txOptions, + storageNodeKey, + param, + 100000n, + 1n * CERE + ); + + const result = await sendTx(sadmin, tx); + log(getExplorerUrl(result), "\n"); + } + } + + const clustersIds = []; + { + for (let key in ddcEnvConfig.cluster) { + console.log("5. clusterCreate "); + + const tx1 = bucketContract.tx.clusterCreate( + txOptions, + JSON.stringify(ddcEnvConfig.cluster[key].param) + ); + + const result1 = await sendTx(sadmin, tx1); + log(getExplorerUrl(result1), "\n"); + const { clusterId } = ddcBucket.findClusterCreatedEvent(result1.contractEvents); + clustersIds.push(clusterId); + + const tx2 = bucketContract.tx.clusterReserveResource( + txOptions, + clusterId, + 100000n + ); + const result2 = await sendTx(sadmin, tx2); + log(getExplorerUrl(result2), "\n"); + } + } + + // TODO: Add Storage nodes and CDN nodes to clusters + + process.exit(0); +} + + +main().then(log, log); \ No newline at end of file diff --git a/scripts/deployment/deploy.js b/scripts/deployment/deploy.js index db7ddbdb..f4c84976 100644 --- a/scripts/deployment/deploy.js +++ b/scripts/deployment/deploy.js @@ -30,7 +30,7 @@ const deployContract = async ( log("From account", account.address); if (maybeCodeHash) { - deploymentRegistry.initContracts(); + deploymentRegistry.initDefaultContracts(); } await deploy( diff --git a/scripts/examples/ddcBucketDemo.js b/scripts/examples/ddcBucketDemo.js index b02c6e61..2edcbc6b 100644 --- a/scripts/examples/ddcBucketDemo.js +++ b/scripts/examples/ddcBucketDemo.js @@ -19,7 +19,7 @@ const BUCKET_CONTRACT_NAME = config.DDC_BUCKET_CONTRACT_NAME; const SEED = config.ACTOR_SEED; const RPC = config.DEVNET_RPC_ENDPOINT; -deploymentRegistry.initContracts(); +deploymentRegistry.initDefaultContracts(); async function main() { const {api, chainName, getExplorerUrl} = await connect(RPC); diff --git a/scripts/examples/ddcBucketPrint.js b/scripts/examples/ddcBucketPrint.js index 2558f333..5d6e5530 100644 --- a/scripts/examples/ddcBucketPrint.js +++ b/scripts/examples/ddcBucketPrint.js @@ -13,7 +13,7 @@ const CONTRACT_NAME = config.DDC_BUCKET_CONTRACT_NAME; const RPC = config.DEVNET_RPC_ENDPOINT; const ACCOUNT_FILTER = null; // get data about all accounts. -deploymentRegistry.initContracts(); +deploymentRegistry.initDefaultContracts(); async function main() { const {api, chainName} = await connect(RPC); diff --git a/scripts/examples/ddcNftRegistryDemo.js b/scripts/examples/ddcNftRegistryDemo.js index c56f2743..26c6aa72 100644 --- a/scripts/examples/ddcNftRegistryDemo.js +++ b/scripts/examples/ddcNftRegistryDemo.js @@ -17,7 +17,7 @@ const NFT_REGISTRY_CONTRACT_NAME = config.DDC_NFT_REGISTRY_CONTRACT_NAME; const SEED = config.ACTOR_SEED; const RPC = config.DEVNET_RPC_ENDPOINT; -deploymentRegistry.initContracts(); +deploymentRegistry.initDefaultContracts(); async function main() { const {api, chainName, getExplorerUrl} = await connect(RPC); diff --git a/scripts/package.json b/scripts/package.json index d7122bb0..22eab1b1 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -9,6 +9,7 @@ "demo-nft-registry": "yarn ensure-deps && node examples/ddcNftRegistryDemo.js", "deploy-ddc-bucket": "yarn ensure-deps && node deployment/ddcBucketDeploy.js", "deploy-ddc-nft-registry": "yarn ensure-deps && node deployment/ddcNftRegistryDeploy.js", - "print-ddc-bucket": "yarn ensure-deps && node examples/ddcBucketPrint.js" + "print-ddc-bucket": "yarn ensure-deps && node examples/ddcBucketPrint.js", + "ddc-setup": "yarn ensure-deps && node ddc-setup/ddcSetup.js" } } \ No newline at end of file diff --git a/scripts/sdk/src/deploymentRegistry.js b/scripts/sdk/src/deploymentRegistry.js index de060568..96cd965a 100644 --- a/scripts/sdk/src/deploymentRegistry.js +++ b/scripts/sdk/src/deploymentRegistry.js @@ -5,7 +5,7 @@ const ddcBucketAbi = require("./abi/ddc_bucket.json"); const ddcNftRegistryAbi = require("./abi/ddc_nft_registry.json"); -function initContracts() { +function initDefaultContracts() { registerABI(config.DDC_BUCKET_CONTRACT_NAME, ddcBucketAbi); @@ -43,7 +43,16 @@ function initContracts() { } +function initContract(name, env, address) { + registerABI(name, ddcBucketAbi); + registerContract( + name, + env, + address + ); +} module.exports = { - initContracts, + initDefaultContracts, + initContract } diff --git a/scripts/sdk/src/polkadotWrappers.js b/scripts/sdk/src/polkadotWrappers.js index e36e6eb5..7151fc61 100644 --- a/scripts/sdk/src/polkadotWrappers.js +++ b/scripts/sdk/src/polkadotWrappers.js @@ -22,10 +22,15 @@ async function connect(rpcUrl) { } function randomAccount() { - const mnemonic = mnemonicGenerate(12); const keyring = new Keyring({type: 'sr25519'}); - const account =keyring.addFromMnemonic(mnemonic); - return account; + const mnemonic = mnemonicGenerate(12); + const account = keyring.addFromMnemonic(mnemonic); + + return { + account, + mnemonic, + address: account.address, + }; } function accountFromUri(uri) { From b63a031587dc1e8222c437f83a4ced587cedb7ac Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 3 Jul 2023 13:12:05 +0200 Subject: [PATCH 78/89] feat(cluster): endpoint for resseting v_nodes on a node within a cluster --- bucket/ddc_bucket/cluster/messages.rs | 58 +++++++- bucket/ddc_bucket/tests/env_utils.rs | 1 + bucket/ddc_bucket/tests/test_cluster.rs | 178 ++++++++++++++++++++++++ bucket/ddc_bucket/topology/store.rs | 12 ++ bucket/lib.rs | 54 +++++++ 5 files changed, 297 insertions(+), 6 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 2d6a129b..eb380721 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -14,7 +14,7 @@ use crate::ddc_bucket::{ BASIS_POINTS, AccountId, Balance, ClusterCreated, ClusterNodeAdded, ClusterNodeRemoved, ClusterCdnNodeAdded, ClusterCdnNodeRemoved, ClusterDistributeRevenues, ClusterReserveResource, ClusterDistributeCdnRevenues, - ClusterRemoved, ClusterParamsSet, ClusterNodeStatusSet, ClusterCdnNodeStatusSet, PermissionGranted, PermissionRevoked, + ClusterRemoved, ClusterParamsSet, ClusterNodeStatusSet, ClusterCdnNodeStatusSet, PermissionGranted, PermissionRevoked, ClusterNodeReset, DdcBucket, NodeStatusInCluster, Result, Error::* }; @@ -123,12 +123,15 @@ impl DdcBucket { pub fn message_cluster_replace_node( &mut self, cluster_id: ClusterId, - v_nodes: Vec, + v_nodes: Vec, new_node_key: NodeKey, ) -> Result<()> { let caller = Self::env().caller(); let cluster = self.clusters.get(cluster_id)?; + let mut new_node = self.nodes.get(new_node_key)?; + new_node.only_with_cluster(cluster_id)?; + cluster.only_manager(caller)?; // Give back resources to the old node for all its v_nodes for v_node in &v_nodes { @@ -139,10 +142,6 @@ impl DdcBucket { old_node.put_resource(cluster.resource_per_v_node); self.nodes.update(old_node_key, &old_node)?; - let mut new_node = self.nodes.get(new_node_key)?; - new_node.only_with_cluster(cluster_id)?; - cluster.only_manager(caller)?; - // Reserve resources on the new node. new_node.take_resource(cluster.resource_per_v_node)?; self.nodes.update(new_node_key, &new_node)?; @@ -163,6 +162,53 @@ impl DdcBucket { } + pub fn message_cluster_reset_node( + &mut self, + cluster_id: ClusterId, + node_key: NodeKey, + new_v_nodes: Vec, + ) -> Result<()> { + let caller = Self::env().caller(); + + let cluster = self.clusters.get(cluster_id)?; + + let mut node = self.nodes.get(node_key)?; + node.only_with_cluster(cluster_id)?; + cluster.only_manager(caller)?; + + let old_v_nodes = self.topology.get_v_nodes_by_node(node_key); + + if new_v_nodes.len() > old_v_nodes.len() { + + for _i in 0..new_v_nodes.len() - old_v_nodes.len() { + node.take_resource(cluster.resource_per_v_node)?; + self.nodes.update(node_key, &node)?; + } + + } else if new_v_nodes.len() < old_v_nodes.len() { + + for _i in 0..old_v_nodes.len() - new_v_nodes.len() { + node.put_resource(cluster.resource_per_v_node); + self.nodes.update(node_key, &node)?; + } + + } + + self.topology.reset_node( + cluster_id, + node_key, + new_v_nodes + )?; + + Self::env().emit_event(ClusterNodeReset { + cluster_id, + node_key: node_key, + }); + + Ok(()) + } + + pub fn message_cluster_add_cdn_node( &mut self, cluster_id: ClusterId, diff --git a/bucket/ddc_bucket/tests/env_utils.rs b/bucket/ddc_bucket/tests/env_utils.rs index 5551e208..9ca19645 100644 --- a/bucket/ddc_bucket/tests/env_utils.rs +++ b/bucket/ddc_bucket/tests/env_utils.rs @@ -59,6 +59,7 @@ pub fn print_events(events: &[Event]) { match ev { Event::ClusterCreated(ev) => println!("EVENT {:?}", ev), Event::ClusterNodeReplaced(ev) => println!("EVENT {:?}", ev), + Event::ClusterNodeReset(ev) => println!("EVENT {:?}", ev), Event::ClusterReserveResource(ev) => println!("EVENT {:?}", ev), Event::ClusterDistributeRevenues(ev) => println!("EVENT {:?}", ev), Event::NodeCreated(ev) => println!("EVENT {:?}", ev), diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 976ca822..f5e58749 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -1016,6 +1016,31 @@ fn cluster_replace_node_err_if_no_v_nodes() { } +#[ink::test] +fn cluster_replace_node_err_if_node_is_not_in_cluster() { + let mut ctx = setup_cluster(); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + set_caller_value(ctx.provider_id0, 10); + ctx.contract.node_create( + new_node_key, + NodeParams::from("new_node"), + 1000000000, + 1 + )?; + + set_caller_value(ctx.manager_id, 10); + assert_eq!( + ctx.contract.cluster_replace_node( + ctx.cluster_id, + vec![1, 3], + new_node_key + ), + Err(NodeIsNotAddedToCluster(ctx.cluster_id)) + ); +} + + #[ink::test] fn cluster_replace_node_err_if_v_nodes_exceeds_limit() { let mut ctx = setup_cluster(); @@ -1123,6 +1148,159 @@ fn cluster_replace_node_ok() { } +#[ink::test] +fn cluster_reset_node_err_if_not_cluster_manager() { + let mut ctx = setup_cluster(); + + let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + set_caller_value(not_manager_id, 0); + + // Reassign a vnode from node1 to node2. + assert_eq!( + ctx.contract.cluster_reset_node( + ctx.cluster_id, + ctx.node_key2, + vec![10, 11, 12], + ), + Err(OnlyClusterManager) + ); +} + + +#[ink::test] +fn cluster_reset_node_err_if_node_does_not_exist() { + let mut ctx = setup_cluster(); + + let bad_node_key = AccountId::from([0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, 0x9c, 0x76]); + set_caller(ctx.manager_id); + assert_eq!( + ctx.contract.cluster_reset_node( + ctx.cluster_id, + bad_node_key, + vec![10, 11, 12], + ), + Err(NodeDoesNotExist) + ); +} + + +#[ink::test] +fn cluster_reset_node_err_if_no_v_nodes() { + let mut ctx = setup_cluster(); + + assert_eq!( + ctx.contract.cluster_reset_node( + ctx.cluster_id, + ctx.node_key2, + vec![], + ), + Err(AtLeastOneVNodeHasToBeAssigned(ctx.cluster_id, ctx.node_key2)) + ); +} + + +#[ink::test] +fn cluster_reset_node_err_if_v_nodes_exceeds_limit() { + let mut ctx = setup_cluster(); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + set_caller_value(ctx.provider_id0, 10); + ctx.contract.node_create( + new_node_key, + NodeParams::from("new_node"), + 1000000000, + 1 + )?; + + set_caller_value(ctx.manager_id, 10); + ctx.contract.cluster_add_node( + ctx.cluster_id, + new_node_key, + vec![100], + )?; + + let v_nodes: Vec = vec![100; 1801]; + assert_eq!( + ctx.contract.cluster_reset_node( + ctx.cluster_id, + new_node_key, + v_nodes, + ), + Err(VNodesSizeExceedsLimit) + ); +} + + +#[ink::test] +fn cluster_reset_node_err_if_node_is_not_in_cluster() { + let mut ctx = setup_cluster(); + + let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + set_caller_value(ctx.provider_id0, 10); + ctx.contract.node_create( + new_node_key, + NodeParams::from("new_node"), + 1000000000, + 1 + )?; + + set_caller_value(ctx.manager_id, 10); + assert_eq!( + ctx.contract.cluster_reset_node( + ctx.cluster_id, + new_node_key, + vec![10, 11, 12], + ), + Err(NodeIsNotAddedToCluster(ctx.cluster_id)) + ); +} + + +#[ink::test] +fn cluster_reset_node_ok() { + let mut ctx = setup_cluster(); + + set_caller(ctx.manager_id); + // Reset vnode for node1 + ctx.contract.cluster_reset_node( + ctx.cluster_id, + ctx.node_key1, + vec![10, 11, 12], + )?; + + // Check the last event + let ev = get_events().pop().unwrap(); + assert!(matches!(ev, Event::ClusterNodeReset(ev) if ev == + ClusterNodeReset { + cluster_id: ctx.cluster_id, + node_key: ctx.node_key1 + } + )); + + let mut cluster_v_nodes = Vec::::new(); + cluster_v_nodes.extend(ctx.v_nodes0.clone()); + cluster_v_nodes.extend(vec![10, 11, 12]); + cluster_v_nodes.extend(ctx.v_nodes2.clone()); + cluster_v_nodes.sort(); + + let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; + cluster_info.cluster_v_nodes.sort(); + assert_eq!(&cluster_info.cluster_v_nodes, &cluster_v_nodes, "a v_node must be replaced"); + + let mut v_nodes0 = ctx.contract.get_v_nodes_by_node(ctx.node_key0.clone()); + v_nodes0.sort(); + let mut v_nodes1 = ctx.contract.get_v_nodes_by_node(ctx.node_key1.clone()); + v_nodes1.sort(); + let mut v_nodes2 = ctx.contract.get_v_nodes_by_node(ctx.node_key2.clone()); + v_nodes2.sort(); + + assert_eq!(&v_nodes0, &vec![1, 2, 3], "v_nodes must not be reset for the 1st node"); + assert_eq!(&v_nodes1, &vec![10, 11, 12], "v_nodes must not be reset for the 2nd node"); + assert_eq!(&v_nodes2, &vec![7, 8, 9], "v_nodes must not be reset to the 3rd node"); + +} + + #[ink::test] fn cluster_reserve_resource_ok() { let mut ctx = setup_cluster(); diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index 88cf7f17..ba8d2a8a 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -194,6 +194,18 @@ impl TopologyStore { } + pub fn reset_node( + &mut self, + cluster_id: ClusterId, + node_key: NodeKey, + new_v_nodes: Vec, + ) -> Result<()> { + + self.remove_node(cluster_id, node_key)?; + self.add_node(cluster_id, node_key, new_v_nodes) + + } + pub fn remove_topology( &mut self, cluster_id: ClusterId, diff --git a/bucket/lib.rs b/bucket/lib.rs index eb5d057e..6b348dc9 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -358,6 +358,16 @@ pub mod ddc_bucket { node_key: NodeKey, } + /// A vnode was re-assigned to new node. + #[ink(event)] + #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] + pub struct ClusterNodeReset { + #[ink(topic)] + cluster_id: ClusterId, + #[ink(topic)] + node_key: NodeKey, + } + /// Some resources were reserved for the cluster from the nodes. #[ink(event)] #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] @@ -532,6 +542,50 @@ pub mod ddc_bucket { ) } + + /// Reeset a Storage node in the targeting cluster. + /// + /// This endpoint resets virtual nodes on a physical Storage node in the targeting cluster. + /// Virtual nodes determines a token (position) on the ring in terms of Consistent Hashing. + /// The Storage node can be reset in the cluster by cluster manager only. + /// + /// # Parameters + /// + /// * `cluster_id` - ID of the targeting cluster. + /// * `node_key` - Public Key associated with the Storage node. + /// * `new_v_nodes` - List of tokens (positions) related to the Storage node to reset. + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Events + /// + /// * `ClusterNodeAdded` event on successful Storage node addition. + /// + /// # Errors + /// + /// * `ClusterDoesNotExist` error if the cluster does not exist. + /// * `OnlyTrustedClusterManager` error if the caller is not a trusted cluster manager. + /// * `NodeDoesNotExist` error if the adding Storage node does not exist. + /// * `NodeIsAddedToCluster(ClusterId)` error if the adding Storage node is already added to this or another cluster. + /// * `AtLeastOneVNodeHasToBeAssigned(ClusterId, NodeKey)` error if there is a Storage node without any virtual nodes in the cluster. + /// * `VNodesSizeExceedsLimit` error if virtual nodes length exceeds storage capacity. + #[ink(message)] + pub fn cluster_reset_node( + &mut self, + cluster_id: ClusterId, + node_key: NodeKey, + new_v_nodes: Vec, + ) -> Result<()> { + self.message_cluster_reset_node( + cluster_id, + node_key, + new_v_nodes + ) + } + + /// Adds a CDN node to the targeting cluster. /// /// This endpoint adds a CDN node to the targeting cluster. From aa4d01d5073382546937b5d8accfb8c3c46a9697 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 3 Jul 2023 14:28:09 +0200 Subject: [PATCH 79/89] fix(cluster): reserving or releasing node resources while resetting a node --- bucket/ddc_bucket/cdn_node/entity.rs | 4 ---- bucket/ddc_bucket/cluster/messages.rs | 24 ++++++++++++++++-------- bucket/ddc_bucket/node/entity.rs | 10 +++------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index 1b927718..e6718ef2 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -97,10 +97,6 @@ impl CdnNode { self.status_in_cluster = Some(status); } - pub fn cdn_account_id(&self) -> AccountId { - self.provider_id - } - pub fn put_payment(&mut self, amount: Balance) { self.undistributed_payment += amount; } diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index eb380721..0ddecef9 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -67,6 +67,7 @@ impl DdcBucket { cluster.add_node(node_key)?; for _v_node in &v_nodes { + node.reserve_resource(cluster.resource_per_v_node)?; cluster.total_rent += node.rent_per_month; } self.clusters.update(cluster_id, &cluster)?; @@ -105,6 +106,7 @@ impl DdcBucket { cluster.remove_node(node_key); let v_nodes = self.topology.get_v_nodes_by_node(node_key); for _v_node in &v_nodes { + node.release_resource(cluster.resource_per_v_node); cluster.total_rent -= node.rent_per_month; } self.clusters.update(cluster_id, &cluster)?; @@ -139,11 +141,11 @@ impl DdcBucket { // Give back resources to the old node let mut old_node = self.nodes.get(old_node_key)?; - old_node.put_resource(cluster.resource_per_v_node); + old_node.release_resource(cluster.resource_per_v_node); self.nodes.update(old_node_key, &old_node)?; // Reserve resources on the new node. - new_node.take_resource(cluster.resource_per_v_node)?; + new_node.reserve_resource(cluster.resource_per_v_node)?; self.nodes.update(new_node_key, &new_node)?; } @@ -170,7 +172,7 @@ impl DdcBucket { ) -> Result<()> { let caller = Self::env().caller(); - let cluster = self.clusters.get(cluster_id)?; + let mut cluster = self.clusters.get(cluster_id)?; let mut node = self.nodes.get(node_key)?; node.only_with_cluster(cluster_id)?; @@ -181,17 +183,22 @@ impl DdcBucket { if new_v_nodes.len() > old_v_nodes.len() { for _i in 0..new_v_nodes.len() - old_v_nodes.len() { - node.take_resource(cluster.resource_per_v_node)?; - self.nodes.update(node_key, &node)?; + node.reserve_resource(cluster.resource_per_v_node)?; + cluster.total_rent += node.rent_per_month; } + self.nodes.update(node_key, &node)?; + self.clusters.update(cluster_id, &cluster)?; + } else if new_v_nodes.len() < old_v_nodes.len() { for _i in 0..old_v_nodes.len() - new_v_nodes.len() { - node.put_resource(cluster.resource_per_v_node); - self.nodes.update(node_key, &node)?; + node.release_resource(cluster.resource_per_v_node); + cluster.total_rent -= node.rent_per_month; } + self.nodes.update(node_key, &node)?; + self.clusters.update(cluster_id, &cluster)?; } self.topology.reset_node( @@ -410,7 +417,7 @@ impl DdcBucket { for v_node in cluster_v_nodes { let node_key = self.topology.get_node_by_v_node(cluster_id, v_node)?; let mut node = self.nodes.get(node_key)?; - node.take_resource(resource)?; + node.reserve_resource(resource)?; self.nodes.update(node_key, &node)?; } @@ -418,6 +425,7 @@ impl DdcBucket { cluster_id, resource, }); + Ok(()) } diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index b0503c83..5a5bf3ba 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -126,16 +126,12 @@ impl Node { pub fn change_status_in_cluster(&mut self, status: NodeStatusInCluster) { self.status_in_cluster = Some(status); } - - pub fn revenue_account_id(&self) -> AccountId { - self.provider_id - } - - pub fn put_resource(&mut self, amount: Resource) { + + pub fn release_resource(&mut self, amount: Resource) { self.free_resource += amount; } - pub fn take_resource(&mut self, amount: Resource) -> Result<()> { + pub fn reserve_resource(&mut self, amount: Resource) -> Result<()> { if self.free_resource >= amount { self.free_resource -= amount; Ok(()) From 531bf6739f19cf3aeafc11bdb57208e014dd28ff Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 3 Jul 2023 17:05:03 +0200 Subject: [PATCH 80/89] fix(cluster): setting resource value that is being used by virtual nodes --- bucket/ddc_bucket/bucket/messages.rs | 2 +- bucket/ddc_bucket/cluster/entity.rs | 11 +- bucket/ddc_bucket/cluster/messages.rs | 59 ++-- bucket/ddc_bucket/cluster/store.rs | 6 +- bucket/ddc_bucket/node/entity.rs | 6 +- bucket/ddc_bucket/node/messages.rs | 6 +- bucket/ddc_bucket/node/store.rs | 4 +- bucket/ddc_bucket/tests/setup_utils.rs | 55 ++-- bucket/ddc_bucket/tests/test_bucket.rs | 11 +- bucket/ddc_bucket/tests/test_cluster.rs | 365 +++++++++++++----------- bucket/ddc_bucket/tests/test_node.rs | 24 +- bucket/lib.rs | 92 ++++-- scripts/sdk/src/abi/ddc_bucket.json | 8 +- 13 files changed, 375 insertions(+), 274 deletions(-) diff --git a/bucket/ddc_bucket/bucket/messages.rs b/bucket/ddc_bucket/bucket/messages.rs index 148988a3..37d33576 100644 --- a/bucket/ddc_bucket/bucket/messages.rs +++ b/bucket/ddc_bucket/bucket/messages.rs @@ -31,7 +31,7 @@ impl DdcBucket { let mut bucket = self.buckets.get(bucket_id)?; let mut cluster = self.clusters.get(bucket.cluster_id)?; Self::only_owner_or_cluster_manager(&bucket, &cluster)?; - + // todo: fix resource allocation cluster.take_resource(resource)?; self.clusters.update(bucket.cluster_id, &cluster)?; bucket.put_resource(resource); diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 3151543c..d3de0da5 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -64,13 +64,14 @@ impl Cluster { pub fn new( manager_id: AccountId, cluster_params: ClusterParams, + resource_per_v_node: Resource, ) -> Result { let mut cluster = Cluster { manager_id, cluster_params: ClusterParams::default(), nodes_keys: Vec::new(), - resource_per_v_node: 0, + resource_per_v_node, resource_used: 0, revenues: Cash(0), total_rent: 0, @@ -138,12 +139,8 @@ impl Cluster { rent } - pub fn set_rent(&mut self, rent: Balance) { - self.total_rent = rent; - } - - pub fn put_resource(&mut self, amount: Resource) { - self.resource_per_v_node += amount; + pub fn set_resource_per_v_node(&mut self, resource_per_v_node: Resource) { + self.resource_per_v_node = resource_per_v_node; } pub fn take_resource(&mut self, amount: Resource) -> Result<()> { diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 0ddecef9..ea4fcf54 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -27,12 +27,14 @@ impl DdcBucket { pub fn message_cluster_create( &mut self, cluster_params: ClusterParams, + resource_per_v_node: Resource, ) -> Result { let caller = Self::env().caller(); let cluster_id = self.clusters.create( caller, - cluster_params.clone() + cluster_params.clone(), + resource_per_v_node )?; self.topology.create_topology(cluster_id)?; @@ -63,13 +65,13 @@ impl DdcBucket { cluster.only_manager(caller)?; node.set_cluster(cluster_id, NodeStatusInCluster::ADDING); - self.nodes.update(node_key, &node)?; - cluster.add_node(node_key)?; for _v_node in &v_nodes { node.reserve_resource(cluster.resource_per_v_node)?; - cluster.total_rent += node.rent_per_month; + cluster.total_rent += node.rent_v_node_per_month; } + + self.nodes.update(node_key, &node)?; self.clusters.update(cluster_id, &cluster)?; self.topology.add_node(cluster_id, node_key, v_nodes)?; @@ -101,14 +103,14 @@ impl DdcBucket { node.only_with_cluster(cluster_id)?; node.unset_cluster(); - self.nodes.update(node_key, &node)?; - cluster.remove_node(node_key); let v_nodes = self.topology.get_v_nodes_by_node(node_key); for _v_node in &v_nodes { node.release_resource(cluster.resource_per_v_node); - cluster.total_rent -= node.rent_per_month; + cluster.total_rent -= node.rent_v_node_per_month; } + + self.nodes.update(node_key, &node)?; self.clusters.update(cluster_id, &cluster)?; self.topology.remove_node(cluster_id, node_key)?; @@ -180,21 +182,22 @@ impl DdcBucket { let old_v_nodes = self.topology.get_v_nodes_by_node(node_key); - if new_v_nodes.len() > old_v_nodes.len() { - - for _i in 0..new_v_nodes.len() - old_v_nodes.len() { - node.reserve_resource(cluster.resource_per_v_node)?; - cluster.total_rent += node.rent_per_month; - } - self.nodes.update(node_key, &node)?; - self.clusters.update(cluster_id, &cluster)?; + if new_v_nodes.len() != old_v_nodes.len() { - } else if new_v_nodes.len() < old_v_nodes.len() { + if new_v_nodes.len() > old_v_nodes.len() { + + for _i in 0..new_v_nodes.len() - old_v_nodes.len() { + node.reserve_resource(cluster.resource_per_v_node)?; + cluster.total_rent += node.rent_v_node_per_month; + } - for _i in 0..old_v_nodes.len() - new_v_nodes.len() { - node.release_resource(cluster.resource_per_v_node); - cluster.total_rent -= node.rent_per_month; + } else if new_v_nodes.len() < old_v_nodes.len() { + + for _i in 0..old_v_nodes.len() - new_v_nodes.len() { + node.release_resource(cluster.resource_per_v_node); + cluster.total_rent -= node.rent_v_node_per_month; + } } self.nodes.update(node_key, &node)?; @@ -402,30 +405,34 @@ impl DdcBucket { } - pub fn message_cluster_reserve_resource( + pub fn message_cluster_set_resource_per_v_node( &mut self, cluster_id: ClusterId, - resource: Resource, + new_resource_per_v_node: Resource, ) -> Result<()> { let caller = Self::env().caller(); let mut cluster = self.clusters.get(cluster_id)?; cluster.only_manager(caller)?; - cluster.put_resource(resource); - self.clusters.update(cluster_id, &cluster)?; + let old_resource_per_v_node = cluster.resource_per_v_node; + + cluster.set_resource_per_v_node(new_resource_per_v_node); let cluster_v_nodes = self.topology.get_v_nodes_by_cluster(cluster_id); for v_node in cluster_v_nodes { let node_key = self.topology.get_node_by_v_node(cluster_id, v_node)?; let mut node = self.nodes.get(node_key)?; - node.reserve_resource(resource)?; + node.release_resource(old_resource_per_v_node); + node.reserve_resource(new_resource_per_v_node)?; self.nodes.update(node_key, &node)?; } + self.clusters.update(cluster_id, &cluster)?; + Self::env().emit_event(ClusterReserveResource { cluster_id, - resource, + resource: new_resource_per_v_node, }); - + Ok(()) } diff --git a/bucket/ddc_bucket/cluster/store.rs b/bucket/ddc_bucket/cluster/store.rs index de973076..0f1b970c 100644 --- a/bucket/ddc_bucket/cluster/store.rs +++ b/bucket/ddc_bucket/cluster/store.rs @@ -2,7 +2,7 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_storage::Mapping; -use crate::ddc_bucket::{AccountId, Error::*, Result}; +use crate::ddc_bucket::{AccountId, Resource, Error::*, Result}; use super::entity::{Cluster, ClusterId, ClusterParams}; @@ -18,13 +18,15 @@ impl ClusterStore { &mut self, manager_id: AccountId, cluster_params: ClusterParams, + resource_per_v_node: Resource, ) -> Result { let cluster_id = self.next_cluster_id; self.next_cluster_id = self.next_cluster_id + 1; let cluster = Cluster::new( manager_id, - cluster_params + cluster_params, + resource_per_v_node )?; self.clusters.insert(&cluster_id, &cluster); diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index 5a5bf3ba..b090b7ad 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -20,7 +20,7 @@ pub type Resource = u32; #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] pub struct Node { pub provider_id: ProviderId, - pub rent_per_month: Balance, + pub rent_v_node_per_month: Balance, pub free_resource: Resource, pub node_params: NodeParams, pub cluster_id: Option, @@ -72,13 +72,13 @@ impl Node { provider_id: AccountId, node_params: NodeParams, capacity: Resource, - rent_per_month: Balance, + rent_v_node_per_month: Balance, ) -> Result { let mut node = Node { provider_id, node_params: NodeParams::default(), free_resource: capacity, - rent_per_month, + rent_v_node_per_month, cluster_id: None, status_in_cluster: None, }; diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index 460324de..bb838c2e 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -13,7 +13,7 @@ impl DdcBucket { node_key: NodeKey, node_params: NodeParams, capacity: Resource, - rent_per_month: Balance, + rent_v_node_per_month: Balance, ) -> Result { let caller = Self::env().caller(); @@ -22,13 +22,13 @@ impl DdcBucket { caller, node_params.clone(), capacity, - rent_per_month + rent_v_node_per_month )?; Self::env().emit_event(NodeCreated { node_key, provider_id: caller, - rent_per_month, + rent_v_node_per_month, node_params, }); diff --git a/bucket/ddc_bucket/node/store.rs b/bucket/ddc_bucket/node/store.rs index e5f1f2cd..4f8c911b 100644 --- a/bucket/ddc_bucket/node/store.rs +++ b/bucket/ddc_bucket/node/store.rs @@ -25,7 +25,7 @@ impl NodeStore { provider_id: AccountId, node_params: NodeParams, capacity: Resource, - rent_per_month: Balance, + rent_v_node_per_month: Balance, ) -> Result { if self.nodes.contains(&node_key) { @@ -40,7 +40,7 @@ impl NodeStore { provider_id, node_params, capacity, - rent_per_month + rent_v_node_per_month )?; self.nodes.insert(node_key, &node); diff --git a/bucket/ddc_bucket/tests/setup_utils.rs b/bucket/ddc_bucket/tests/setup_utils.rs index 132ff3d5..4b362880 100644 --- a/bucket/ddc_bucket/tests/setup_utils.rs +++ b/bucket/ddc_bucket/tests/setup_utils.rs @@ -34,6 +34,12 @@ pub struct TestCluster { pub v_nodes0: Vec, pub v_nodes1: Vec, pub v_nodes2: Vec, + pub node_capacity0: u32, + pub node_capacity1: u32, + pub node_capacity2: u32, + pub rent_v_node_per_month0: Balance, + pub rent_v_node_per_month1: Balance, + pub rent_v_node_per_month2: Balance, pub cdn_node_key0: CdnNodeKey, pub cdn_node_key1: CdnNodeKey, @@ -48,9 +54,9 @@ pub struct TestCluster { pub cluster_v_nodes: Vec, pub nodes_keys: Vec, pub cdn_nodes_keys: Vec, - pub rent_per_month: Balance, - pub capacity: u32, - pub reserved_resource: u32, + pub resource_per_v_node: Resource, + // pub rent_v_node_per_month: Balance, + // pub reserved_resource: u32, } pub fn setup_cluster() -> TestCluster { @@ -67,44 +73,48 @@ pub fn setup_cluster() -> TestCluster { set_balance(provider_id2, 1000 * TOKEN); set_balance(manager_id, 1000 * TOKEN); - let rent_per_month: Balance = 10 * TOKEN; - let reserved_resource = 10; - let capacity = 100; - + // let rent_v_node_per_month: Balance = 10 * TOKEN; + // let reserved_resource = 10; // Create the 1st storage node let node_key0 = AccountId::from([0x0a; 32]); let node_params0 = NodeParams::from("{\"url\":\"https://ddc.cere.network/storage/0\"}"); + let node_capacity0 = 100; + let rent_v_node_per_month0 = 10 * TOKEN; set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); contract.node_create( node_key0, node_params0.clone(), - capacity, - rent_per_month + node_capacity0, + rent_v_node_per_month0, ).unwrap(); // Create the 2nd storage node let node_key1 = AccountId::from([0x0b; 32]); let node_params1 = NodeParams::from("{\"url\":\"https://ddc-1.cere.network/storage/1\"}"); + let node_capacity1 = 100; + let rent_v_node_per_month1 = 10 * TOKEN; set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); contract.node_create( node_key1, node_params1.clone(), - capacity, - rent_per_month + node_capacity1, + rent_v_node_per_month1 ).unwrap(); // Create the 3rd storage node let node_key2 = AccountId::from([0x0c; 32]); let node_params2 = NodeParams::from("{\"url\":\"https://ddc-2.cere.network/storage/2\"}"); + let node_capacity2 = 100; + let rent_v_node_per_month2 = 10 * TOKEN; set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); let node_key2 = contract.node_create( node_key2, node_params2.clone(), - capacity, - rent_per_month, + node_capacity2, + rent_v_node_per_month2, ).unwrap(); @@ -140,9 +150,11 @@ pub fn setup_cluster() -> TestCluster { // Create a Cluster let cluster_params = ClusterParams::from("{}"); + let resource_per_v_node = 10; set_caller_value(manager_id, CONTRACT_FEE_LIMIT); let cluster_id = contract.cluster_create( cluster_params.clone(), + resource_per_v_node ).unwrap(); @@ -208,11 +220,6 @@ pub fn setup_cluster() -> TestCluster { cdn_node_key2, ).unwrap(); - - set_caller(manager_id); - contract.cluster_reserve_resource(cluster_id, reserved_resource).unwrap(); - - let nodes_keys = vec![ node_key0, node_key1, @@ -246,6 +253,9 @@ pub fn setup_cluster() -> TestCluster { v_nodes0, v_nodes1, v_nodes2, + rent_v_node_per_month0, + rent_v_node_per_month1, + rent_v_node_per_month2, cdn_node_key0, cdn_node_key1, @@ -253,16 +263,17 @@ pub fn setup_cluster() -> TestCluster { cdn_node_params0, cdn_node_params1, cdn_node_params2, + node_capacity0, + node_capacity1, + node_capacity2, manager_id, cluster_id, cluster_params, - cluster_v_nodes, - rent_per_month, nodes_keys, cdn_nodes_keys, - capacity, - reserved_resource, + cluster_v_nodes, + resource_per_v_node, } } diff --git a/bucket/ddc_bucket/tests/test_bucket.rs b/bucket/ddc_bucket/tests/test_bucket.rs index 4214c261..9f64e830 100644 --- a/bucket/ddc_bucket/tests/test_bucket.rs +++ b/bucket/ddc_bucket/tests/test_bucket.rs @@ -12,7 +12,10 @@ fn do_bucket_pays_cluster( test_bucket: &TestBucket, usd_per_cere: Balance, ) -> Result<()> { - let expected_rent = ctx.rent_per_month * ctx.cluster_v_nodes.len() as Balance; + let expected_rent = + ctx.rent_v_node_per_month0 * ctx.v_nodes0.len() as Balance + + ctx.rent_v_node_per_month1 * ctx.v_nodes1.len() as Balance + + ctx.rent_v_node_per_month2 * ctx.v_nodes2.len() as Balance; // Check the state before payment. let before = ctx @@ -115,7 +118,11 @@ fn bucket_create_ok() { let test_bucket = &setup_bucket(ctx); // Check the structure of the bucket including the payment flow. - let total_rent = ctx.rent_per_month * ctx.cluster_v_nodes.len() as Balance; + let total_rent = + ctx.rent_v_node_per_month0 * ctx.v_nodes0.len() as Balance + + ctx.rent_v_node_per_month1 * ctx.v_nodes1.len() as Balance + + ctx.rent_v_node_per_month2 * ctx.v_nodes2.len() as Balance; + let bucket_params = BucketParams::from(""); let expect_bucket = Bucket { owner_id: test_bucket.owner_id, diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index f5e58749..24cbec1a 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -15,145 +15,153 @@ fn cluster_create_ok() { let cdn_node_keys = &[ctx.cdn_node_key0, ctx.cdn_node_key1, ctx.cdn_node_key2]; let node_params = &[ctx.node_params0.clone(), ctx.node_params1.clone(), ctx.node_params2.clone()]; let cdn_node_params = &[ctx.cdn_node_params0.clone(), ctx.cdn_node_params1.clone(), ctx.cdn_node_params2.clone()]; - + let rent_v_node_per_month = &[ctx.rent_v_node_per_month0.clone(), ctx.rent_v_node_per_month1.clone(), ctx.rent_v_node_per_month2.clone()]; + assert_eq!(ctx.cluster_id, 0, "cluster_id must start at 0"); // Check cluster Storage nodes - { - let node0 = ctx.contract.node_get(ctx.node_key0)?; - let v_nodes0 = ctx.contract.get_v_nodes_by_node(ctx.node_key0); + + let node0 = ctx.contract.node_get(ctx.node_key0)?; + let v_nodes0 = ctx.contract.get_v_nodes_by_node(ctx.node_key0); + let v_nodes0_len : u32 = v_nodes0.len().try_into().unwrap(); - assert_eq!( - node0, - NodeInfo { - node_key: ctx.node_key0, - node: Node { - provider_id: ctx.provider_id0, - rent_per_month: ctx.rent_per_month, - free_resource: ctx.capacity - ctx.reserved_resource * 3, - node_params: ctx.node_params0.clone(), - cluster_id: Some(ctx.cluster_id), - status_in_cluster: Some(NodeStatusInCluster::ADDING), - }, - v_nodes: v_nodes0 - } - ); + assert_eq!( + node0, + NodeInfo { + node_key: ctx.node_key0, + node: Node { + provider_id: ctx.provider_id0, + rent_v_node_per_month: ctx.rent_v_node_per_month0, + free_resource: ctx.node_capacity0 - ctx.resource_per_v_node * v_nodes0_len, + node_params: ctx.node_params0.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + v_nodes: v_nodes0 + } + ); - let node1 = ctx.contract.node_get(ctx.node_key1)?; - let v_nodes1 = ctx.contract.get_v_nodes_by_node(ctx.node_key1); + let node1 = ctx.contract.node_get(ctx.node_key1)?; + let v_nodes1 = ctx.contract.get_v_nodes_by_node(ctx.node_key1); + let v_nodes1_len : u32 = v_nodes1.len().try_into().unwrap(); - assert_eq!( - node1, - NodeInfo { - node_key: ctx.node_key1, - node: Node { - provider_id: ctx.provider_id1, - rent_per_month: ctx.rent_per_month, - free_resource: ctx.capacity - ctx.reserved_resource * 3, - node_params: ctx.node_params1.clone(), - cluster_id: Some(ctx.cluster_id), - status_in_cluster: Some(NodeStatusInCluster::ADDING), - }, - v_nodes: v_nodes1 - } - ); + assert_eq!( + node1, + NodeInfo { + node_key: ctx.node_key1, + node: Node { + provider_id: ctx.provider_id1, + rent_v_node_per_month: ctx.rent_v_node_per_month1, + free_resource: ctx.node_capacity1 - ctx.resource_per_v_node * v_nodes1_len, + node_params: ctx.node_params1.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + v_nodes: v_nodes1 + } + ); - let node2 = ctx.contract.node_get(ctx.node_key2)?; - let v_nodes2 = ctx.contract.get_v_nodes_by_node(ctx.node_key2); + let node2 = ctx.contract.node_get(ctx.node_key2)?; + let v_nodes2 = ctx.contract.get_v_nodes_by_node(ctx.node_key2); + let v_nodes2_len : u32 = v_nodes2.len().try_into().unwrap(); - assert_eq!( - node2, - NodeInfo { - node_key: ctx.node_key2, - node: Node { - provider_id: ctx.provider_id2, - rent_per_month: ctx.rent_per_month, - free_resource: ctx.capacity - ctx.reserved_resource * 3, - node_params: ctx.node_params2.clone(), - cluster_id: Some(ctx.cluster_id), - status_in_cluster: Some(NodeStatusInCluster::ADDING), - }, - v_nodes: v_nodes2 - } - ); - } + assert_eq!( + node2, + NodeInfo { + node_key: ctx.node_key2, + node: Node { + provider_id: ctx.provider_id2, + rent_v_node_per_month: ctx.rent_v_node_per_month2, + free_resource: ctx.node_capacity2 - ctx.resource_per_v_node * v_nodes2_len, + node_params: ctx.node_params2.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + v_nodes: v_nodes2 + } + ); // Check cluster CDN nodes - { - let cdn_node0 = ctx.contract.cdn_node_get(ctx.cdn_node_key0)?; + + let cdn_node0 = ctx.contract.cdn_node_get(ctx.cdn_node_key0)?; - assert_eq!( + assert_eq!( - cdn_node0, - CdnNodeInfo { - cdn_node_key: ctx.cdn_node_key0, - cdn_node: CdnNode { - provider_id: ctx.provider_id0, - undistributed_payment: 0, - cdn_node_params: ctx.cdn_node_params0.clone(), - cluster_id: Some(ctx.cluster_id), - status_in_cluster: Some(NodeStatusInCluster::ADDING), - }, - } - ); + cdn_node0, + CdnNodeInfo { + cdn_node_key: ctx.cdn_node_key0, + cdn_node: CdnNode { + provider_id: ctx.provider_id0, + undistributed_payment: 0, + cdn_node_params: ctx.cdn_node_params0.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + } + ); - let cdn_node1 = ctx.contract.cdn_node_get(ctx.cdn_node_key1)?; + let cdn_node1 = ctx.contract.cdn_node_get(ctx.cdn_node_key1)?; - assert_eq!( - cdn_node1, - CdnNodeInfo { - cdn_node_key: ctx.cdn_node_key1, - cdn_node: CdnNode { - provider_id: ctx.provider_id1, - undistributed_payment: 0, - cdn_node_params: ctx.cdn_node_params1.clone(), - cluster_id: Some(ctx.cluster_id), - status_in_cluster: Some(NodeStatusInCluster::ADDING), - }, - } - ); + assert_eq!( + cdn_node1, + CdnNodeInfo { + cdn_node_key: ctx.cdn_node_key1, + cdn_node: CdnNode { + provider_id: ctx.provider_id1, + undistributed_payment: 0, + cdn_node_params: ctx.cdn_node_params1.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + } + ); - let cdn_node2 = ctx.contract.cdn_node_get(ctx.cdn_node_key2)?; + let cdn_node2 = ctx.contract.cdn_node_get(ctx.cdn_node_key2)?; - assert_eq!( - cdn_node2, - CdnNodeInfo { - cdn_node_key: ctx.cdn_node_key2, - cdn_node: CdnNode { - provider_id: ctx.provider_id2, - undistributed_payment: 0, - cdn_node_params: ctx.cdn_node_params2.clone(), - cluster_id: Some(ctx.cluster_id), - status_in_cluster: Some(NodeStatusInCluster::ADDING), - }, - } - ); - } + assert_eq!( + cdn_node2, + CdnNodeInfo { + cdn_node_key: ctx.cdn_node_key2, + cdn_node: CdnNode { + provider_id: ctx.provider_id2, + undistributed_payment: 0, + cdn_node_params: ctx.cdn_node_params2.clone(), + cluster_id: Some(ctx.cluster_id), + status_in_cluster: Some(NodeStatusInCluster::ADDING), + }, + } + ); + // Check the cluster - { - let cluster = ctx.contract.cluster_get(ctx.cluster_id)?; - let cluster_v_nodes = ctx.contract.get_v_nodes_by_cluster(ctx.cluster_id); - assert_eq!( - cluster, - ClusterInfo { - cluster_id: ctx.cluster_id, - cluster: Cluster { - manager_id: ctx.manager_id, - nodes_keys: ctx.nodes_keys, - resource_per_v_node: ctx.reserved_resource, - resource_used: 0, - cluster_params: ctx.cluster_params.clone(), - revenues: Cash(0), - total_rent: ctx.rent_per_month * ctx.cluster_v_nodes.len() as Balance, - cdn_nodes_keys: ctx.cdn_nodes_keys, - cdn_usd_per_gb: CDN_USD_PER_GB, - cdn_revenues: Cash(0), - }, - cluster_v_nodes - } - ); - } + + let cluster = ctx.contract.cluster_get(ctx.cluster_id)?; + let cluster_v_nodes = ctx.contract.get_v_nodes_by_cluster(ctx.cluster_id); + let total_rent = + ctx.rent_v_node_per_month0 * v_nodes0_len as Balance + + ctx.rent_v_node_per_month1 * v_nodes1_len as Balance + + ctx.rent_v_node_per_month2 * v_nodes2_len as Balance; + + assert_eq!( + cluster, + ClusterInfo { + cluster_id: ctx.cluster_id, + cluster: Cluster { + manager_id: ctx.manager_id, + nodes_keys: ctx.nodes_keys, + resource_per_v_node: ctx.resource_per_v_node, + resource_used: 0, + cluster_params: ctx.cluster_params.clone(), + revenues: Cash(0), + total_rent, + cdn_nodes_keys: ctx.cdn_nodes_keys, + cdn_usd_per_gb: CDN_USD_PER_GB, + cdn_revenues: Cash(0), + }, + cluster_v_nodes + } + ); + // Check emitted events let mut events = get_events(); @@ -165,7 +173,7 @@ fn cluster_create_ok() { NodeCreated { node_key: node_keys[i], provider_id: providers_ids[i], - rent_per_month: ctx.rent_per_month, + rent_v_node_per_month: rent_v_node_per_month[i], node_params: node_params[i].clone() }) ); @@ -223,16 +231,7 @@ fn cluster_create_ok() { }) ); } - - // Cluster resource reserved event - assert!( - matches!(events.pop().unwrap(), Event::ClusterReserveResource(ev) if ev == - ClusterReserveResource { - cluster_id: ctx.cluster_id, - resource: ctx.reserved_resource - }) - ); - + assert_eq!(events.len(), 0, "All events must be checked"); } @@ -246,7 +245,10 @@ fn cluster_add_node_err_if_node_is_in_cluster() { set_balance(another_manager_id, 1000 * TOKEN); set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - let another_cluster_id = ctx.contract.cluster_create(ClusterParams::from("{}"))?; + let another_cluster_id = ctx.contract.cluster_create( + ClusterParams::from("{}"), + 10 + )?; assert_eq!( ctx.contract.cluster_add_node( @@ -268,7 +270,8 @@ fn cluster_add_node_err_if_not_trusted_manager() { set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); let another_cluster_id = ctx.contract.cluster_create( - ClusterParams::from("{}") + ClusterParams::from("{}"), + 10 )?; let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); @@ -306,7 +309,8 @@ fn cluster_add_node_err_if_not_cluster_manager() { set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); let another_cluster_id = ctx.contract.cluster_create( - ClusterParams::from("{}") + ClusterParams::from("{}"), + 10 )?; let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); @@ -399,7 +403,7 @@ fn cluster_add_node_ok() { set_balance(new_provider_id, 1000 * TOKEN); let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); - let new_node_rent_per_month = 100; + let new_node_rent_v_node_per_month = 100; let new_node_params = NodeParams::from("new_node"); let new_node_capacity = 1000; @@ -408,7 +412,7 @@ fn cluster_add_node_ok() { new_node_key, new_node_params.clone(), new_node_capacity, - new_node_rent_per_month + new_node_rent_v_node_per_month )?; assert!( @@ -416,7 +420,7 @@ fn cluster_add_node_ok() { NodeCreated { node_key: new_node_key, provider_id: new_provider_id, - rent_per_month: new_node_rent_per_month, + rent_v_node_per_month: new_node_rent_v_node_per_month, node_params: new_node_params.clone(), }) ); @@ -474,7 +478,7 @@ fn cluster_add_node_ok() { node_key: new_node_key, node: Node { provider_id: new_provider_id, - rent_per_month: new_node_rent_per_month, + rent_v_node_per_month: new_node_rent_v_node_per_month, free_resource: new_node_capacity, node_params: new_node_params, cluster_id: Some(ctx.cluster_id), @@ -556,7 +560,7 @@ fn cluster_remove_node_ok_if_node_provider() { ]; let _cluster_v_nodes = vec![ - ctx.v_nodes0, + ctx.v_nodes0.clone(), ctx.v_nodes2, ]; @@ -566,12 +570,13 @@ fn cluster_remove_node_ok_if_node_provider() { assert!(matches!(cluster_info.cluster_v_nodes, _cluster_v_nodes)); let node_info = ctx.contract.node_get(ctx.node_key1)?; + let v_nodes0_len : u32 = ctx.v_nodes0.len().try_into().unwrap(); let _expected_node_info = NodeInfo { node_key: ctx.node_key1, node: Node { provider_id: ctx.provider_id1, - rent_per_month: ctx.rent_per_month, - free_resource: ctx.capacity - ctx.reserved_resource * 3, + rent_v_node_per_month: ctx.rent_v_node_per_month1, + free_resource: ctx.node_capacity1 - ctx.resource_per_v_node * v_nodes0_len, node_params: ctx.node_params1, cluster_id: None, status_in_cluster: None @@ -618,12 +623,14 @@ fn cluster_remove_node_ok_if_cluster_manager() { )); let node_info = ctx.contract.node_get(ctx.node_key2)?; + let v_nodes2_len : u32 = ctx.v_nodes2.len().try_into().unwrap(); + let _expected_node_info = NodeInfo { node_key: ctx.node_key2, node: Node { provider_id: ctx.provider_id2, - rent_per_month: ctx.rent_per_month, - free_resource: ctx.capacity - ctx.reserved_resource * 3, + rent_v_node_per_month: ctx.rent_v_node_per_month2, + free_resource: ctx.node_capacity2 - ctx.resource_per_v_node * v_nodes2_len, node_params: ctx.node_params2, cluster_id: None, status_in_cluster: None @@ -643,7 +650,10 @@ fn cluster_add_cdn_node_err_if_cdn_node_is_in_cluster() { set_balance(another_manager_id, 1000 * TOKEN); set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - let another_cluster_id = ctx.contract.cluster_create(ClusterParams::from("{}"))?; + let another_cluster_id = ctx.contract.cluster_create( + ClusterParams::from("{}"), + 10 + )?; assert_eq!( ctx.contract.cluster_add_cdn_node( @@ -663,7 +673,10 @@ fn cluster_add_cdn_node_err_if_not_trusted_manager() { set_balance(another_manager_id, 1000 * TOKEN); set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - let another_cluster_id = ctx.contract.cluster_create(ClusterParams::from("{}"))?; + let another_cluster_id = ctx.contract.cluster_create( + ClusterParams::from("{}"), + 10 + )?; let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); set_balance(new_provider_id, 1000 * TOKEN); @@ -695,7 +708,10 @@ fn cluster_add_cdn_node_err_if_not_cluster_manager() { set_balance(another_manager_id, 1000 * TOKEN); set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - let another_cluster_id = ctx.contract.cluster_create(ClusterParams::from("{}"))?; + let another_cluster_id = ctx.contract.cluster_create( + ClusterParams::from("{}"), + 10 + )?; let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); set_balance(new_provider_id, 1000 * TOKEN); @@ -1131,11 +1147,15 @@ fn cluster_replace_node_ok() { assert_eq!(&v_nodes1, &vec![4, 5, 6], "v_nodes must not be replaced for the 2nd node"); assert_eq!(&v_nodes2, &vec![1, 3, 7, 8, 9], "v_nodes must be assigned to the 3rd node"); + let v_nodes0_len : u32 = v_nodes0.len().try_into().unwrap(); + let v_nodes1_len : u32 = v_nodes1.len().try_into().unwrap(); + let v_nodes2_len : u32 = v_nodes2.len().try_into().unwrap(); + // Check the changed state of the nodes. let expected_resources = [ - (ctx.node_key0, 100 - 10), - (ctx.node_key1, 100 - 10 - 10 - 10), - (ctx.node_key2, 100 - 10 - 10 - 10 - 10 - 10), + (ctx.node_key0, ctx.node_capacity0 - ctx.resource_per_v_node * v_nodes0_len), + (ctx.node_key1, ctx.node_capacity1 - ctx.resource_per_v_node * v_nodes1_len), + (ctx.node_key2, ctx.node_capacity2 - ctx.resource_per_v_node * v_nodes2_len), ]; for (node_key, available) in expected_resources { @@ -1306,27 +1326,33 @@ fn cluster_reserve_resource_ok() { let mut ctx = setup_cluster(); set_caller(ctx.manager_id); + let new_resource_per_v_node = 15; + // Reserve more resources. - ctx.contract.cluster_reserve_resource(ctx.cluster_id, 5)?; + ctx.contract.cluster_set_resource_per_v_node(ctx.cluster_id, new_resource_per_v_node)?; // Check the last event. let ev = get_events().pop().unwrap(); assert!(matches!(ev, Event::ClusterReserveResource(ev) if ev == ClusterReserveResource { cluster_id: ctx.cluster_id, - resource: 5 + resource: new_resource_per_v_node } )); // Check the changed state of the cluster. let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; - assert_eq!(cluster.resource_per_v_node, 10 + 5); + assert_eq!(cluster.resource_per_v_node, new_resource_per_v_node); + + let v_nodes0_len : u32 = ctx.v_nodes0.len().try_into().unwrap(); + let v_nodes1_len : u32 = ctx.v_nodes1.len().try_into().unwrap(); + let v_nodes2_len : u32 = ctx.v_nodes2.len().try_into().unwrap(); // Check the changed state of the nodes. let expected_resources = [ - (ctx.node_key0, 100 - 40 - 5), - (ctx.node_key1, 100 - 40 - 5), - (ctx.node_key2, 100 - 40 - 5), + (ctx.node_key0, ctx.node_capacity0 - new_resource_per_v_node * v_nodes0_len), + (ctx.node_key1, ctx.node_capacity1 - new_resource_per_v_node * v_nodes1_len), + (ctx.node_key2, ctx.node_capacity2 - new_resource_per_v_node * v_nodes2_len), ]; for (node_id, available) in expected_resources { assert_eq!( @@ -1622,6 +1648,11 @@ fn cluster_get_ok() { cluster_v_nodes1.extend(ctx.v_nodes1.clone()); cluster_v_nodes1.extend(ctx.v_nodes2.clone()); + let total_rent = + ctx.rent_v_node_per_month0 * ctx.v_nodes0.len() as Balance + + ctx.rent_v_node_per_month1 * ctx.v_nodes1.len() as Balance + + ctx.rent_v_node_per_month2 * ctx.v_nodes2.len() as Balance; + assert_eq!( ctx.contract.cluster_get(ctx.cluster_id), Ok({ @@ -1630,11 +1661,11 @@ fn cluster_get_ok() { cluster: Cluster { manager_id: ctx.manager_id, nodes_keys: ctx.nodes_keys, - resource_per_v_node: ctx.reserved_resource, + resource_per_v_node: ctx.resource_per_v_node, resource_used: 0, cluster_params: ctx.cluster_params.clone(), revenues: Cash(0), - total_rent: ctx.rent_per_month * ctx.cluster_v_nodes.len() as Balance, + total_rent, cdn_nodes_keys: ctx.cdn_nodes_keys, cdn_usd_per_gb: CDN_USD_PER_GB, cdn_revenues: Cash(0), @@ -1655,16 +1686,21 @@ fn cluster_list_ok() { cluster_v_nodes1.extend(ctx.v_nodes1.clone()); cluster_v_nodes1.extend(ctx.v_nodes2.clone()); + let total_rent = + ctx.rent_v_node_per_month0 * ctx.v_nodes0.len() as Balance + + ctx.rent_v_node_per_month1 * ctx.v_nodes1.len() as Balance + + ctx.rent_v_node_per_month2 * ctx.v_nodes2.len() as Balance; + let cluster1 = ClusterInfo { cluster_id: ctx.cluster_id, cluster: Cluster { manager_id: ctx.manager_id, nodes_keys: ctx.nodes_keys, - resource_per_v_node: ctx.reserved_resource, + resource_per_v_node: ctx.resource_per_v_node, resource_used: 0, cluster_params: ctx.cluster_params.clone(), revenues: Cash(0), - total_rent: ctx.rent_per_month * ctx.cluster_v_nodes.len() as Balance, + total_rent, cdn_nodes_keys: ctx.cdn_nodes_keys, cdn_usd_per_gb: CDN_USD_PER_GB, cdn_revenues: Cash(0), @@ -1673,18 +1709,23 @@ fn cluster_list_ok() { }; let cluster_params2 = ClusterParams::from("{}"); + let resource_per_v_node2 = 10; let manager_id2 = AccountId::from([0x82, 0x61, 0x19, 0xd5, 0xcf, 0x47, 0xdc, 0xb9, 0xc6, 0xff, 0x1a, 0x3e, 0x46, 0x03, 0x6d, 0xad, 0x1f, 0xea, 0x66, 0x18, 0x96, 0x2e, 0x4a, 0x5e, 0x89, 0xe0, 0x96, 0x74, 0xcf, 0x80, 0xf1, 0x30]); + set_balance(manager_id2, 1000 * TOKEN); set_caller(manager_id2); - let cluster_id2 = ctx.contract.cluster_create(cluster_params2.clone())?; + let cluster_id2 = ctx.contract.cluster_create( + cluster_params2.clone(), + resource_per_v_node2 + )?; let cluster2 = ClusterInfo { cluster_id: cluster_id2, cluster: Cluster { manager_id: manager_id2, nodes_keys: Vec::new(), - resource_per_v_node: 0, + resource_per_v_node: resource_per_v_node2, resource_used: 0, cluster_params: cluster_params2, revenues: Cash(0), diff --git a/bucket/ddc_bucket/tests/test_node.rs b/bucket/ddc_bucket/tests/test_node.rs index 0ff9493b..f1effe2d 100644 --- a/bucket/ddc_bucket/tests/test_node.rs +++ b/bucket/ddc_bucket/tests/test_node.rs @@ -13,8 +13,8 @@ fn node_create_err_if_node_exists() { ctx.contract.node_create( ctx.node_key1, ctx.node_params1, - ctx.capacity, - ctx.rent_per_month, + ctx.node_capacity1, + ctx.rent_v_node_per_month1, ), Err(NodeAlreadyExists) ); @@ -31,14 +31,14 @@ fn node_create_ok() { let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); let new_node_params = NodeParams::from("{\"url\":\"https://ddc-1.cere.network/storage/new\"}"); let new_node_capacity = 100; - let new_node_rent_per_month: Balance = 10 * TOKEN; + let new_node_rent_v_node_per_month: Balance = 10 * TOKEN; set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); ctx.contract.node_create( new_node_key, new_node_params.clone(), new_node_capacity, - new_node_rent_per_month, + new_node_rent_v_node_per_month, )?; assert!( @@ -46,7 +46,7 @@ fn node_create_ok() { NodeCreated { node_key: new_node_key, provider_id: new_provider_id, - rent_per_month: new_node_rent_per_month, + rent_v_node_per_month: new_node_rent_v_node_per_month, node_params: new_node_params.clone() }) ); @@ -54,7 +54,7 @@ fn node_create_ok() { let node_info = ctx.contract.node_get(new_node_key)?; let _expected_node_info = Node { provider_id: new_provider_id, - rent_per_month: new_node_rent_per_month, + rent_v_node_per_month: new_node_rent_v_node_per_month, free_resource: new_node_capacity, node_params: new_node_params, cluster_id: None, @@ -184,8 +184,8 @@ fn node_get_ok() { node_key: ctx.node_key1, node: Node { provider_id: ctx.provider_id1, - rent_per_month: ctx.rent_per_month, - free_resource: ctx.capacity - ctx.reserved_resource * v_nodes1_len, + rent_v_node_per_month: ctx.rent_v_node_per_month1, + free_resource: ctx.node_capacity1 - ctx.resource_per_v_node * v_nodes1_len, node_params: ctx.node_params1, cluster_id: Some(ctx.cluster_id), status_in_cluster: Some(NodeStatusInCluster::ADDING), @@ -209,8 +209,8 @@ fn node_list_ok() { node_key: ctx.node_key1, node: Node { provider_id: ctx.provider_id1, - rent_per_month: ctx.rent_per_month, - free_resource: ctx.capacity - ctx.reserved_resource * v_nodes1_len, + rent_v_node_per_month: ctx.rent_v_node_per_month1, + free_resource: ctx.node_capacity1 - ctx.resource_per_v_node * v_nodes1_len, cluster_id: Some(ctx.cluster_id), status_in_cluster: Some(NodeStatusInCluster::ADDING), node_params: ctx.node_params1, @@ -223,8 +223,8 @@ fn node_list_ok() { node_key: ctx.node_key2, node: Node { provider_id:ctx.provider_id2, - rent_per_month: ctx.rent_per_month, - free_resource: ctx.capacity - ctx.reserved_resource * v_nodes2_len, + rent_v_node_per_month: ctx.rent_v_node_per_month2, + free_resource: ctx.node_capacity2 - ctx.resource_per_v_node * v_nodes2_len, cluster_id: Some(ctx.cluster_id), status_in_cluster: Some(NodeStatusInCluster::ADDING), node_params: ctx.node_params2, diff --git a/bucket/lib.rs b/bucket/lib.rs index 6b348dc9..a1a463b4 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -406,6 +406,7 @@ pub mod ddc_bucket { /// # Parameters /// /// * `cluster_params` - [Cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. + /// * `resource_per_v_node` - Resource value that will be allocated for every virtual node in the cluster. /// /// # Output /// @@ -422,8 +423,9 @@ pub mod ddc_bucket { pub fn cluster_create( &mut self, cluster_params: ClusterParams, + resource_per_v_node: Resource, ) -> Result { - self.message_cluster_create(cluster_params) + self.message_cluster_create(cluster_params, resource_per_v_node) } /// Adds a Storage node to the targeting cluster. @@ -454,6 +456,7 @@ pub mod ddc_bucket { /// * `NodeIsAddedToCluster(ClusterId)` error if the adding Storage node is already added to this or another cluster. /// * `AtLeastOneVNodeHasToBeAssigned(ClusterId, NodeKey)` error if there is a Storage node without any virtual nodes in the cluster. /// * `VNodesSizeExceedsLimit` error if virtual nodes length exceeds storage capacity. + /// * `InsufficientResources` - error if there is not enough resources in a physical node. #[ink(message, payable)] pub fn cluster_add_node( &mut self, @@ -571,6 +574,7 @@ pub mod ddc_bucket { /// * `NodeIsAddedToCluster(ClusterId)` error if the adding Storage node is already added to this or another cluster. /// * `AtLeastOneVNodeHasToBeAssigned(ClusterId, NodeKey)` error if there is a Storage node without any virtual nodes in the cluster. /// * `VNodesSizeExceedsLimit` error if virtual nodes length exceeds storage capacity. + /// * `InsufficientResources` - error if there is not enough resources in a physical node. #[ink(message)] pub fn cluster_reset_node( &mut self, @@ -654,7 +658,7 @@ pub mod ddc_bucket { /// Sets parameters for the targeting cluster. /// - /// This enpoint updates [cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. + /// This endpoint updates [cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. /// All cluster parameters must be specified as the endpoint works using SET approach. /// /// # Parameters @@ -685,7 +689,7 @@ pub mod ddc_bucket { /// Removes a cluster. /// - /// This enpoint removes the cluster if it does not contain any nodes. + /// This endpoint removes the cluster if it does not contain any nodes. /// Only an empty cluster can be removed. /// /// # Parameters @@ -715,7 +719,7 @@ pub mod ddc_bucket { /// Changes Storage node status. /// - /// This enpoint changes Storage node status in a cluster. + /// This endpoint changes Storage node status in a cluster. /// /// # Parameters /// @@ -752,7 +756,7 @@ pub mod ddc_bucket { /// Changes CDN node status. /// - /// This enpoint changes CDN node status in a cluster. + /// This endpoint changes CDN node status in a cluster. /// /// # Parameters /// @@ -787,9 +791,48 @@ pub mod ddc_bucket { ) } + + /// Sets the resource used per virual node in cluster. + /// + /// This endpoint sets the resource value that is being used by each virtual node in the cluster. + /// If there are existing virtual nodes in the cluster the resource for its physical nodes will be recalculated. + /// + /// # Parameters + /// + /// * `cluster_id` - ID of the targeting cluster. + /// * `new_resource_per_v_node` - Resource value that will be allocated for every virtual node in the cluster. + /// + /// # Output + /// + /// Returns nothing. + /// + /// # Events + /// + /// * `ClusterNodeReplaced` event on successful virtual node reassignment. + /// + /// # Errors + /// + /// * `ClusterDoesNotExist` error if the cluster does not exist. + /// * `OnlyClusterManager` error if the caller is not the cluster manager. + /// * `NodeDoesNotExist` error if the new Storage node does not exist. + /// * `VNodeIsNotAssignedToNode(ClusterId, VNodeToken)` error if the there is some virtual node that is being reasigned, but this virtual node is not assigned to any physical node. + /// * `InsufficientResources` - error if there is not enough resources in a physical node. + #[ink(message)] + pub fn cluster_set_resource_per_v_node( + &mut self, + cluster_id: ClusterId, + new_resource_per_v_node: Resource + ) -> Result<()> { + self.message_cluster_set_resource_per_v_node( + cluster_id, + new_resource_per_v_node + ) + } + + /// Gets a cluster. /// - /// This enpoint gets the targeting cluster along with its parameters, Storage and CDN nodes. + /// This endpoint gets the targeting cluster along with its parameters, Storage and CDN nodes. /// /// # Parameters /// @@ -810,9 +853,10 @@ pub mod ddc_bucket { self.message_cluster_get(cluster_id) } + /// Gets a paginated list of clusters. /// - /// This enpoint gets a paginated list of clusters along with their parameters, Storage and CDN nodes. + /// This endpoint gets a paginated list of clusters along with their parameters, Storage and CDN nodes. /// The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`. /// The optimal `limit` depends on the size of params. /// @@ -835,14 +879,6 @@ pub mod ddc_bucket { self.message_cluster_list(offset, limit, filter_manager_id) } - /// As manager, reserve more resources for the cluster from the free capacity of nodes. - /// - /// The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes). - #[ink(message)] - pub fn cluster_reserve_resource(&mut self, cluster_id: ClusterId, amount: Resource) -> Result<()> { - self.message_cluster_reserve_resource(cluster_id, amount) - } - /// Trigger the distribution of revenues from the cluster to the providers. #[ink(message)] pub fn cluster_distribute_revenues(&mut self, cluster_id: ClusterId) -> Result<()> { @@ -1000,7 +1036,7 @@ pub mod ddc_bucket { /// Removes a CDN node. /// - /// This enpoint removes the targeting CDN Node if it is not added to some cluster. + /// This endpoint removes the targeting CDN Node if it is not added to some cluster. /// Only a node that is not a member of some cluster can be removed. /// /// # Parameters @@ -1030,7 +1066,7 @@ pub mod ddc_bucket { /// Sets parameters for the targeting CDN node. /// - /// This enpoint updates [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. + /// This endpoint updates [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. /// All CDN node parameters must be specified as the endpoint works using SET approach. /// /// # Parameters @@ -1061,7 +1097,7 @@ pub mod ddc_bucket { /// Gets a CDN node. /// - /// This enpoint gets the targeting CDN node along with its parameters. + /// This endpoint gets the targeting CDN node along with its parameters. /// /// # Parameters /// @@ -1084,7 +1120,7 @@ pub mod ddc_bucket { /// Gets a paginated list of CDN nodes. /// - /// This enpoint gets a paginated list of CDN nodes along with their parameters. + /// This endpoint gets a paginated list of CDN nodes along with their parameters. /// The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`. /// The optimal `limit` depends on the size of params. /// @@ -1120,7 +1156,7 @@ pub mod ddc_bucket { node_key: NodeKey, #[ink(topic)] provider_id: AccountId, - rent_per_month: Balance, + rent_v_node_per_month: Balance, node_params: NodeParams, } @@ -1151,7 +1187,7 @@ pub mod ddc_bucket { /// * `node_key` - Public Keys of the Storage node that should be treated as node identifier. /// * `node_params` - [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. /// * `capacity` - Measure used to evaluate physical node hardware resources. - /// * `rent_per_month` - Renting per month. + /// * `rent_v_node_per_month` - Renting per month. /// /// # Output /// @@ -1171,19 +1207,19 @@ pub mod ddc_bucket { node_key: NodeKey, node_params: NodeParams, capacity: Resource, - rent_per_month: Balance + rent_v_node_per_month: Balance ) -> Result { self.message_node_create( node_key, node_params, capacity, - rent_per_month + rent_v_node_per_month ) } /// Removes a Storage node. /// - /// This enpoint removes the targeting Storage Node if it is not added to some cluster. + /// This endpoint removes the targeting Storage Node if it is not added to some cluster. /// Only a node that is not a member of some cluster can be removed. /// /// # Parameters @@ -1213,7 +1249,7 @@ pub mod ddc_bucket { /// Sets parameters for the targeting Storage node. /// - /// This enpoint updates [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. + /// This endpoint updates [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. /// All Storage node parameters must be specified as the endpoint works using SET approach. /// /// # Parameters @@ -1244,7 +1280,7 @@ pub mod ddc_bucket { /// Gets a Storage node. /// - /// This enpoint gets the targeting Storage node along with its parameters. + /// This endpoint gets the targeting Storage node along with its parameters. /// /// # Parameters /// @@ -1267,7 +1303,7 @@ pub mod ddc_bucket { /// Gets a paginated list of Storage nodes. /// - /// This enpoint gets a paginated list of Storage nodes along with their parameters. + /// This endpoint gets a paginated list of Storage nodes along with their parameters. /// The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`. /// The optimal `limit` depends on the size of params. /// @@ -1393,7 +1429,7 @@ pub mod ddc_bucket { impl DdcBucket { /// Checks for permission existence. /// - /// This enpoint checks whether the given account has the given permission. + /// This endpoint checks whether the given account has the given permission. /// Super-admin will always have all permissions. /// /// # Parameters diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index fefd6892..9202e027 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -737,7 +737,7 @@ { "docs": [], "indexed": false, - "label": "rent_per_month", + "label": "rent_v_node_per_month", "type": { "displayName": [ "Balance" @@ -2856,7 +2856,7 @@ } }, { - "label": "rent_per_month", + "label": "rent_v_node_per_month", "type": { "displayName": [ "Balance" @@ -2876,7 +2876,7 @@ " * `node_key` - Public Keys of the Storage node that should be treated as node identifier.", " * `node_params` - [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format.", " * `capacity` - Measure used to evaluate physical node hardware resources.", - " * `rent_per_month` - Renting per month.", + " * `rent_v_node_per_month` - Renting per month.", "", " # Output", "", @@ -4906,7 +4906,7 @@ "typeName": "ProviderId" }, { - "name": "rent_per_month", + "name": "rent_v_node_per_month", "type": 12, "typeName": "Balance" }, From bc4d9d94cca650562fde9e1c464024e867875aa7 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 3 Jul 2023 17:50:00 +0200 Subject: [PATCH 81/89] fix(bucket): bucket resource allocation fixed --- bucket/ddc_bucket/bucket/messages.rs | 23 ++++++++++++++++++----- bucket/ddc_bucket/cluster/entity.rs | 20 +++++++++----------- bucket/ddc_bucket/cluster/messages.rs | 16 +++++++++++----- bucket/ddc_bucket/node/entity.rs | 2 +- bucket/lib.rs | 10 ++++++---- 5 files changed, 45 insertions(+), 26 deletions(-) diff --git a/bucket/ddc_bucket/bucket/messages.rs b/bucket/ddc_bucket/bucket/messages.rs index 37d33576..55125a81 100644 --- a/bucket/ddc_bucket/bucket/messages.rs +++ b/bucket/ddc_bucket/bucket/messages.rs @@ -3,7 +3,7 @@ use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; -use crate::ddc_bucket::{AccountId, BucketAllocated, BucketCreated, BucketSettlePayment, BucketAvailabilityUpdated, BucketParamsSet, DdcBucket, Result}; +use crate::ddc_bucket::{AccountId, Balance, BucketAllocated, BucketCreated, BucketSettlePayment, BucketAvailabilityUpdated, BucketParamsSet, DdcBucket, Result, Error::*}; use crate::ddc_bucket::cluster::entity::{Cluster, ClusterId}; use crate::ddc_bucket::node::entity::Resource; @@ -31,22 +31,31 @@ impl DdcBucket { let mut bucket = self.buckets.get(bucket_id)?; let mut cluster = self.clusters.get(bucket.cluster_id)?; Self::only_owner_or_cluster_manager(&bucket, &cluster)?; - // todo: fix resource allocation - cluster.take_resource(resource)?; + + let cluster_v_nodes = self.get_v_nodes_by_cluster(bucket.cluster_id); + let cluster_v_nodes_len: u32 = cluster_v_nodes.len().try_into().unwrap(); + let max_cluster_resource = cluster_v_nodes_len * cluster.resource_per_v_node; + + if cluster.resource_used + resource > max_cluster_resource { + return Err(InsufficientClusterResources); + } + + cluster.take_resource(resource); self.clusters.update(bucket.cluster_id, &cluster)?; bucket.put_resource(resource); // Start the payment flow to the cluster. - let rent = cluster.get_rent(resource); + let extra_rate = cluster.total_rent * resource as Balance; let now_ms = Self::env().block_timestamp(); - self.accounts.increase_flow(now_ms, rent, &mut bucket.flow)?; + self.accounts.increase_flow(now_ms, extra_rate, &mut bucket.flow)?; self.buckets.update(bucket_id, &bucket)?; Self::env().emit_event(BucketAllocated { bucket_id, cluster_id: bucket.cluster_id, resource }); Ok(()) } + pub fn message_bucket_settle_payment(&mut self, bucket_id: BucketId) -> Result<()> { let mut bucket = self.buckets.get(bucket_id)?; @@ -73,11 +82,13 @@ impl DdcBucket { Ok(()) } + pub fn message_bucket_get(&self, bucket_id: BucketId) -> Result { let bucket = self.buckets.get(bucket_id)?; self.bucket_calculate_status(bucket_id, bucket) } + pub fn message_bucket_list(&self, offset: u32, limit: u32, filter_owner_id: Option) -> (Vec, u32) { let mut bucket_statuses = Vec::with_capacity(limit as usize); for bucket_id in offset..offset + limit { @@ -101,6 +112,7 @@ impl DdcBucket { (bucket_statuses, self.buckets.next_bucket_id) } + pub fn message_bucket_list_for_account(&self, owner_id: AccountId) -> Vec { let mut result : Vec = Vec::new(); @@ -115,6 +127,7 @@ impl DdcBucket { result } + pub fn bucket_calculate_status(&self, bucket_id: BucketId, bucket: Bucket) -> Result { let mut writer_ids = self.buckets.get_bucket_readers(bucket_id); writer_ids.push(bucket.owner_id); diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index d3de0da5..1638fd6f 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -134,22 +134,20 @@ impl Cluster { Ok(()) } - pub fn get_rent(&self, resource: Resource) -> Balance { - let rent = self.total_rent * resource as Balance; - rent + pub fn increase_rent(&mut self, amount: Balance) { + self.total_rent += amount; } - + + pub fn decrease_rent(&mut self, amount: Balance) { + self.total_rent -= amount; + } + pub fn set_resource_per_v_node(&mut self, resource_per_v_node: Resource) { self.resource_per_v_node = resource_per_v_node; } - pub fn take_resource(&mut self, amount: Resource) -> Result<()> { - let used = self.resource_used + amount; - if used > self.resource_per_v_node { - return Err(InsufficientResources); - } - self.resource_used = used; - Ok(()) + pub fn take_resource(&mut self, amount: Resource) { + self.resource_used = self.resource_used + amount; } pub fn cdn_get_revenue_cere(&self) -> Cash { diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index ea4fcf54..88006d04 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -68,7 +68,7 @@ impl DdcBucket { cluster.add_node(node_key)?; for _v_node in &v_nodes { node.reserve_resource(cluster.resource_per_v_node)?; - cluster.total_rent += node.rent_v_node_per_month; + cluster.increase_rent(node.rent_v_node_per_month); } self.nodes.update(node_key, &node)?; @@ -99,7 +99,6 @@ impl DdcBucket { && !node.only_provider(caller).is_ok() { return Err(OnlyClusterManagerOrNodeProvider); } - node.only_with_cluster(cluster_id)?; node.unset_cluster(); @@ -107,7 +106,7 @@ impl DdcBucket { let v_nodes = self.topology.get_v_nodes_by_node(node_key); for _v_node in &v_nodes { node.release_resource(cluster.resource_per_v_node); - cluster.total_rent -= node.rent_v_node_per_month; + cluster.decrease_rent(node.rent_v_node_per_month); } self.nodes.update(node_key, &node)?; @@ -189,14 +188,14 @@ impl DdcBucket { for _i in 0..new_v_nodes.len() - old_v_nodes.len() { node.reserve_resource(cluster.resource_per_v_node)?; - cluster.total_rent += node.rent_v_node_per_month; + cluster.increase_rent(node.rent_v_node_per_month); } } else if new_v_nodes.len() < old_v_nodes.len() { for _i in 0..old_v_nodes.len() - new_v_nodes.len() { node.release_resource(cluster.resource_per_v_node); - cluster.total_rent -= node.rent_v_node_per_month; + cluster.decrease_rent(node.rent_v_node_per_month); } } @@ -418,6 +417,13 @@ impl DdcBucket { cluster.set_resource_per_v_node(new_resource_per_v_node); let cluster_v_nodes = self.topology.get_v_nodes_by_cluster(cluster_id); + let cluster_v_nodes_len: u32 = cluster_v_nodes.len().try_into().unwrap(); + + let new_max_cluster_resource = cluster_v_nodes_len * new_resource_per_v_node; + if cluster.resource_used > new_max_cluster_resource { + return Err(InsufficientClusterResources); + } + for v_node in cluster_v_nodes { let node_key = self.topology.get_node_by_v_node(cluster_id, v_node)?; let mut node = self.nodes.get(node_key)?; diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index b090b7ad..da10d002 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -136,7 +136,7 @@ impl Node { self.free_resource -= amount; Ok(()) } else { - Err(InsufficientResources) + Err(InsufficientNodeResources) } } diff --git a/bucket/lib.rs b/bucket/lib.rs index a1a463b4..dd5e8500 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -456,7 +456,7 @@ pub mod ddc_bucket { /// * `NodeIsAddedToCluster(ClusterId)` error if the adding Storage node is already added to this or another cluster. /// * `AtLeastOneVNodeHasToBeAssigned(ClusterId, NodeKey)` error if there is a Storage node without any virtual nodes in the cluster. /// * `VNodesSizeExceedsLimit` error if virtual nodes length exceeds storage capacity. - /// * `InsufficientResources` - error if there is not enough resources in a physical node. + /// * `InsufficientNodeResources` - error if there is not enough resources in a physical node. #[ink(message, payable)] pub fn cluster_add_node( &mut self, @@ -574,7 +574,7 @@ pub mod ddc_bucket { /// * `NodeIsAddedToCluster(ClusterId)` error if the adding Storage node is already added to this or another cluster. /// * `AtLeastOneVNodeHasToBeAssigned(ClusterId, NodeKey)` error if there is a Storage node without any virtual nodes in the cluster. /// * `VNodesSizeExceedsLimit` error if virtual nodes length exceeds storage capacity. - /// * `InsufficientResources` - error if there is not enough resources in a physical node. + /// * `InsufficientNodeResources` - error if there is not enough resources in a physical node. #[ink(message)] pub fn cluster_reset_node( &mut self, @@ -816,7 +816,8 @@ pub mod ddc_bucket { /// * `OnlyClusterManager` error if the caller is not the cluster manager. /// * `NodeDoesNotExist` error if the new Storage node does not exist. /// * `VNodeIsNotAssignedToNode(ClusterId, VNodeToken)` error if the there is some virtual node that is being reasigned, but this virtual node is not assigned to any physical node. - /// * `InsufficientResources` - error if there is not enough resources in a physical node. + /// * `InsufficientClusterResources` - error if there is not enough resources in the cluster. + /// * `InsufficientNodeResources` - error if there is not enough resources in a physical node. #[ink(message)] pub fn cluster_set_resource_per_v_node( &mut self, @@ -1765,7 +1766,8 @@ pub mod ddc_bucket { BondingPeriodNotFinished, TransferFailed, InsufficientBalance, - InsufficientResources, + InsufficientNodeResources, + InsufficientClusterResources, EraSettingFailed } From a7b2098b08d3460264119004805916ec901b263e Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 3 Jul 2023 20:23:18 +0200 Subject: [PATCH 82/89] chore(protocol): setting fee values for admin --- bucket/ddc_bucket/admin.rs | 28 ++++++++- bucket/ddc_bucket/cluster/messages.rs | 4 +- bucket/ddc_bucket/protocol/messages.rs | 31 +++------- bucket/ddc_bucket/protocol/store.rs | 78 +++++++++++++++++++------- bucket/lib.rs | 42 +++++++++----- 5 files changed, 122 insertions(+), 61 deletions(-) diff --git a/bucket/ddc_bucket/admin.rs b/bucket/ddc_bucket/admin.rs index 7514b4fb..9d7636d0 100644 --- a/bucket/ddc_bucket/admin.rs +++ b/bucket/ddc_bucket/admin.rs @@ -1,11 +1,11 @@ //! The privileged interface for admin tasks. - +use ink_lang::codegen::{EmitEvent, StaticEnv}; use crate::ddc_bucket::perm::entity::Permission; -use crate::ddc_bucket::{AccountId, Balance, Cash, DdcBucket, NodeKey, +use crate::ddc_bucket::{AccountId, Balance, Cash, Payable, DdcBucket, NodeKey, NetworkFeeConfig, NodeOwnershipTransferred, CdnNodeOwnershipTransferred, PermissionGranted, PermissionRevoked, Result, + BasisPoints, Error::* }; -use ink_lang::codegen::{EmitEvent, StaticEnv}; impl DdcBucket { @@ -103,4 +103,26 @@ impl DdcBucket { Self::send_cash(admin, Cash(amount)) } + pub fn message_admin_set_protocol_fee_bp(&mut self, protocol_fee_bp: BasisPoints) -> Result<()> { + self.only_with_permission(Permission::SuperAdmin)?; + self.protocol.set_protocol_fee_bp(protocol_fee_bp); + Ok(()) + } + + + pub fn message_admin_set_network_fee_config(&mut self, config: NetworkFeeConfig) -> Result<()> { + self.only_with_permission(Permission::SuperAdmin)?; + self.protocol.set_network_fee_config(config); + Ok(()) + } + + + pub fn message_admin_withdraw_revenues(&mut self, amount: u128) -> Result<()> { + self.only_with_permission(Permission::SuperAdmin)?; + self.protocol.withdraw_revenues(Payable(amount))?; + Self::send_cash(self.protocol.get_protocol_fee_dest(), Cash(amount))?; + Ok(()) + } + + } diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 88006d04..7d3ea57d 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -497,7 +497,7 @@ impl DdcBucket { // Charge the cluster management fee. self.capture_fee( - self.protocol.cluster_management_fee_bp(), + self.protocol.get_cluster_management_fee_bp(), cluster.manager_id, &mut cluster.revenues, )?; @@ -635,7 +635,7 @@ impl DdcBucket { // Charge the cluster management fee. self.capture_fee( - self.protocol.cluster_management_fee_bp(), + self.protocol.get_cluster_management_fee_bp(), cluster.manager_id, &mut cluster.cdn_revenues )?; diff --git a/bucket/ddc_bucket/protocol/messages.rs b/bucket/ddc_bucket/protocol/messages.rs index 952c03fa..8a8d18d3 100644 --- a/bucket/ddc_bucket/protocol/messages.rs +++ b/bucket/ddc_bucket/protocol/messages.rs @@ -1,35 +1,20 @@ //! The public interface to manage Protocol (fees included). -use crate::ddc_bucket::{DdcBucket, Result}; -use crate::ddc_bucket::cash::{Cash, Payable}; -use crate::ddc_bucket::perm::entity::Permission; +use crate::ddc_bucket::{DdcBucket, NetworkFeeConfig, BasisPoints}; +use crate::ddc_bucket::cash::Cash; impl DdcBucket { - pub fn message_get_protocol_fee_bp(&self) -> u128 { + pub fn message_get_protocol_fee_bp(&self) -> BasisPoints { self.protocol.get_protocol_fee_bp() } - pub fn message_set_protocol_fee_bp(&mut self, protocol_fee_bp: u128) -> Result<()> { - self.only_with_permission(Permission::SuperAdmin)?; - self.protocol.set_protocol_fee_bp(protocol_fee_bp); - Ok(()) + pub fn message_get_network_fee_config(&self) -> NetworkFeeConfig { + self.protocol.get_network_fee_config() } - - pub fn message_get_fee_revenues(&self) -> Cash { - self.protocol.get_fee_revenues() - } - - pub fn message_put_fee_revenues(&mut self, amount: Cash) -> Result<()> { - self.protocol.put_revenues(amount); - Ok(()) - } - - pub fn message_withdraw_revenues(&mut self, amount: u128) -> Result<()> { - self.only_with_permission(Permission::SuperAdmin)?; - self.protocol.withdraw_revenues(Payable(amount))?; - Self::send_cash(self.protocol.protocol_fee_destination, Cash(amount))?; - Ok(()) + + pub fn message_get_protocol_revenues(&self) -> Cash { + self.protocol.get_revenues() } } \ No newline at end of file diff --git a/bucket/ddc_bucket/protocol/store.rs b/bucket/ddc_bucket/protocol/store.rs index 1df93501..8683bcf9 100644 --- a/bucket/ddc_bucket/protocol/store.rs +++ b/bucket/ddc_bucket/protocol/store.rs @@ -1,14 +1,9 @@ use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout}; - use scale::{Decode, Encode}; - -use crate::ddc_bucket::{DdcBucket, AccountId, Error::*, Result, Balance, BASIS_POINTS}; +use crate::ddc_bucket::{DdcBucket, AccountId, Error::*, Result, Balance, BasisPoints, BASIS_POINTS}; use crate::ddc_bucket::cash::{Cash, Payable}; use crate::ddc_bucket::currency::CurrencyConverter; -use crate::ddc_bucket::perm::entity::Permission; - -pub type BasisPoints = u128; /// The configuration of fees. #[derive(Default, Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] @@ -22,10 +17,26 @@ pub struct NetworkFeeConfig { pub cluster_management_fee_bp: BasisPoints, } +impl NetworkFeeConfig { + + pub fn new( + network_fee_bp: BasisPoints, + network_fee_destination: AccountId, + cluster_management_fee_bp: BasisPoints + ) -> Self { + Self { + network_fee_bp, + network_fee_destination, + cluster_management_fee_bp + } + } + +} + #[derive(Default, Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug, scale_info::TypeInfo))] pub struct ProtocolStore { - pub protocol_fee_bp: u128, + pub protocol_fee_bp: BasisPoints, pub protocol_fee_destination: AccountId, pub revenues: Cash, pub curr_converter: CurrencyConverter, @@ -34,21 +45,37 @@ pub struct ProtocolStore { impl ProtocolStore { - pub fn init(&mut self, protocol_fee_destination: AccountId, protocol_fee_bp: u128) { + pub fn init( + &mut self, + protocol_fee_bp: BasisPoints, + protocol_fee_dest: AccountId, + network_fee_bp: BasisPoints, + network_fee_dest: AccountId, + cluster_fee_bp: BasisPoints, + ) { self.protocol_fee_bp = protocol_fee_bp; - self.protocol_fee_destination = protocol_fee_destination; + self.protocol_fee_destination = protocol_fee_dest; self.curr_converter = CurrencyConverter::new(); + self.network_fee_config = NetworkFeeConfig::new( + network_fee_bp, + network_fee_dest, + cluster_fee_bp + ); } - pub fn get_protocol_fee_bp(&self) -> u128 { + pub fn get_protocol_fee_bp(&self) -> BasisPoints { self.protocol_fee_bp } - pub fn set_protocol_fee_bp(&mut self, protocol_fee_bp: u128) { + pub fn set_protocol_fee_bp(&mut self, protocol_fee_bp: BasisPoints) { self.protocol_fee_bp = protocol_fee_bp; } - pub fn get_fee_revenues(&self) -> Cash { + pub fn get_protocol_fee_dest(&self) -> AccountId { + self.protocol_fee_destination + } + + pub fn get_revenues(&self) -> Cash { self.revenues } @@ -64,7 +91,23 @@ impl ProtocolStore { Ok(()) } - pub fn cluster_management_fee_bp(&self) -> BasisPoints { + pub fn get_network_fee_config(&self) -> NetworkFeeConfig { + self.network_fee_config.clone() + } + + pub fn set_network_fee_config(&mut self, config: NetworkFeeConfig) { + self.network_fee_config = config; + } + + pub fn get_network_fee_bp(&self) -> BasisPoints { + self.network_fee_config.network_fee_bp + } + + pub fn get_network_fee_dest(&self) -> AccountId { + self.network_fee_config.network_fee_destination + } + + pub fn get_cluster_management_fee_bp(&self) -> BasisPoints { self.network_fee_config.cluster_management_fee_bp } @@ -74,8 +117,8 @@ impl DdcBucket { /// Take a network fee from the given revenues (in place). pub fn capture_network_fee(&mut self, revenues: &mut Cash) -> Result<()> { self.capture_fee( - self.protocol.network_fee_config.network_fee_bp, - self.protocol.network_fee_config.network_fee_destination, + self.protocol.get_network_fee_bp(), + self.protocol.get_network_fee_dest(), revenues ) } @@ -88,9 +131,4 @@ impl DdcBucket { Self::send_cash(destination, cash) } - pub fn message_admin_set_network_fee_config(&mut self, config: NetworkFeeConfig) -> Result<()> { - self.only_with_permission(Permission::SuperAdmin)?; - self.protocol.network_fee_config = config; - Ok(()) - } } \ No newline at end of file diff --git a/bucket/lib.rs b/bucket/lib.rs index dd5e8500..fd606f54 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -68,10 +68,15 @@ pub mod ddc_bucket { pub fn new() -> Self { ink_lang::utils::initialize_contract(|contract: &mut Self| { let admin = Self::env().caller(); - // Make the creator of this contract a super-admin. contract.perms.grant_permission(admin, Permission::SuperAdmin); contract.committer.init(admin); - contract.protocol.init(admin, DEFAULT_PROTOCOL_FEE_BP); + contract.protocol.init( + DEFAULT_PROTOCOL_FEE_BP, + admin, + DEFAULT_NETWORK_FEE_BP, + admin, + DEFAULT_CLUSTER_FEE_BP + ); }) } } @@ -1342,7 +1347,13 @@ pub mod ddc_bucket { /// Return fees accumulated by the protocol #[ink(message)] pub fn get_protocol_revenues(&self) -> Cash { - self.message_get_fee_revenues() + self.message_get_protocol_revenues() + } + + /// Get the Fee Percentage Basis Points that will be charged by the protocol + #[ink(message)] + pub fn get_network_fee_config(&self) -> NetworkFeeConfig { + self.message_get_network_fee_config() } } // ---- End Protocol ---- @@ -1666,21 +1677,21 @@ pub mod ddc_bucket { self.message_admin_withdraw(amount) } - /// As SuperAdmin, set the network and cluster fee configuration. + /// Pay the revenues accumulated by the protocol #[ink(message)] - pub fn admin_set_network_fee_config(&mut self, config: NetworkFeeConfig) -> Result<()> { - self.message_admin_set_network_fee_config(config) + pub fn admin_withdraw_protocol_revenues(&mut self, amount: Balance) -> Result<()> { + self.message_admin_withdraw_revenues(amount) } - /// Pay the revenues accumulated by the protocol + /// As SuperAdmin, set the network and cluster fee configuration. #[ink(message)] - pub fn admin_withdraw_protocol_revenues(&mut self, amount: u128) -> Result<()> { - self.message_withdraw_revenues(amount) + pub fn admin_set_network_fee_config(&mut self, config: NetworkFeeConfig) -> Result<()> { + self.message_admin_set_network_fee_config(config) } #[ink(message)] - pub fn admin_set_protocol_fee_bp(&mut self, protocol_fee_bp: u128) -> Result<()> { - self.message_set_protocol_fee_bp(protocol_fee_bp) + pub fn admin_set_protocol_fee_bp(&mut self, protocol_fee_bp: BasisPoints) -> Result<()> { + self.message_admin_set_protocol_fee_bp(protocol_fee_bp) } } @@ -1721,8 +1732,13 @@ pub mod ddc_bucket { // ---- Constants ---- /// One token with 10 decimals. pub const TOKEN: Balance = 10_000_000_000; - pub const BASIS_POINTS: u128 = 10_000; // 100% - pub const DEFAULT_PROTOCOL_FEE_BP: u128 = 500; // 5 % + + pub type BasisPoints = u128; + pub const BASIS_POINTS: BasisPoints = 10_000; // 100% + pub const DEFAULT_PROTOCOL_FEE_BP: BasisPoints = 500; // 5 % + pub const DEFAULT_NETWORK_FEE_BP: BasisPoints = 0; // 0 % + pub const DEFAULT_CLUSTER_FEE_BP: BasisPoints = 0; // 0 % + #[derive(Debug, PartialEq, Eq, Encode, Decode)] From 00b363f4409583ac573e8a7250ed49195f483c37 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 3 Jul 2023 20:52:38 +0200 Subject: [PATCH 83/89] chore(cluster): v_nodes are added to events --- bucket/ddc_bucket/cluster/messages.rs | 12 +++++++----- bucket/ddc_bucket/tests/test_cluster.rs | 25 +++++++++++++++++-------- bucket/lib.rs | 3 +++ scripts/sdk/src/bucket/ddcBucket.js | 3 ++- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 7d3ea57d..1545a541 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -74,11 +74,12 @@ impl DdcBucket { self.nodes.update(node_key, &node)?; self.clusters.update(cluster_id, &cluster)?; - self.topology.add_node(cluster_id, node_key, v_nodes)?; + self.topology.add_node(cluster_id, node_key, v_nodes.clone())?; Self::env().emit_event(ClusterNodeAdded { cluster_id, - node_key + node_key, + v_nodes }); Ok(()) @@ -153,12 +154,13 @@ impl DdcBucket { self.topology.replace_node( cluster_id, new_node_key, - v_nodes + v_nodes.clone() )?; Self::env().emit_event(ClusterNodeReplaced { cluster_id, node_key: new_node_key, + v_nodes, }); Ok(()) @@ -181,7 +183,6 @@ impl DdcBucket { let old_v_nodes = self.topology.get_v_nodes_by_node(node_key); - if new_v_nodes.len() != old_v_nodes.len() { if new_v_nodes.len() > old_v_nodes.len() { @@ -206,12 +207,13 @@ impl DdcBucket { self.topology.reset_node( cluster_id, node_key, - new_v_nodes + new_v_nodes.clone() )?; Self::env().emit_event(ClusterNodeReset { cluster_id, node_key: node_key, + v_nodes: new_v_nodes }); Ok(()) diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 24cbec1a..87d67319 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -12,6 +12,8 @@ fn cluster_create_ok() { let ctx = setup_cluster(); let providers_ids = &[ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; let node_keys = &[ctx.node_key0, ctx.node_key1, ctx.node_key2]; + let v_nodes = &[ctx.v_nodes0.clone(), ctx.v_nodes1.clone(), ctx.v_nodes2.clone()]; + let cdn_node_keys = &[ctx.cdn_node_key0, ctx.cdn_node_key1, ctx.cdn_node_key2]; let node_params = &[ctx.node_params0.clone(), ctx.node_params1.clone(), ctx.node_params2.clone()]; let cdn_node_params = &[ctx.cdn_node_params0.clone(), ctx.cdn_node_params1.clone(), ctx.cdn_node_params2.clone()]; @@ -217,11 +219,13 @@ fn cluster_create_ok() { assert!(matches!(events.pop().unwrap(), Event::ClusterNodeAdded(ev) if ev == ClusterNodeAdded { cluster_id: ctx.cluster_id, - node_key: node_keys[i] + node_key: node_keys[i], + v_nodes: v_nodes[i].clone() }) ); } + // Cluster cdn node added event for i in 0..3 { assert!(matches!(events.pop().unwrap(), Event::ClusterCdnNodeAdded(ev) if ev == @@ -450,7 +454,8 @@ fn cluster_add_node_ok() { matches!(get_events().pop().unwrap(), Event::ClusterNodeAdded(ev) if ev == ClusterNodeAdded { cluster_id: ctx.cluster_id, - node_key: new_node_key + node_key: new_node_key, + v_nodes: new_v_nodes.clone() }) ); @@ -1109,10 +1114,11 @@ fn cluster_replace_node_ok() { let mut ctx = setup_cluster(); set_caller(ctx.manager_id); - // Reassign a vnode from node0 to node2. + // Reassign a vnode from node0 to node2 + let v_nodes_to_reasign: Vec:: = vec![1, 3]; ctx.contract.cluster_replace_node( ctx.cluster_id, - vec![1, 3], + v_nodes_to_reasign.clone(), ctx.node_key2 )?; @@ -1121,7 +1127,8 @@ fn cluster_replace_node_ok() { assert!(matches!(ev, Event::ClusterNodeReplaced(ev) if ev == ClusterNodeReplaced { cluster_id: ctx.cluster_id, - node_key: ctx.node_key2 + node_key: ctx.node_key2, + v_nodes: v_nodes_to_reasign.clone(), } )); @@ -1129,7 +1136,7 @@ fn cluster_replace_node_ok() { cluster_v_nodes.extend(vec![2]); cluster_v_nodes.extend(ctx.v_nodes1.clone()); cluster_v_nodes.extend(ctx.v_nodes2.clone()); - cluster_v_nodes.extend(vec![1, 3]); + cluster_v_nodes.extend(v_nodes_to_reasign.clone()); cluster_v_nodes.sort(); let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; @@ -1282,10 +1289,11 @@ fn cluster_reset_node_ok() { set_caller(ctx.manager_id); // Reset vnode for node1 + let new_v_nodes: Vec:: = vec![10, 11, 12]; ctx.contract.cluster_reset_node( ctx.cluster_id, ctx.node_key1, - vec![10, 11, 12], + new_v_nodes.clone(), )?; // Check the last event @@ -1293,7 +1301,8 @@ fn cluster_reset_node_ok() { assert!(matches!(ev, Event::ClusterNodeReset(ev) if ev == ClusterNodeReset { cluster_id: ctx.cluster_id, - node_key: ctx.node_key1 + node_key: ctx.node_key1, + v_nodes: new_v_nodes } )); diff --git a/bucket/lib.rs b/bucket/lib.rs index fd606f54..d60ffa8b 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -288,6 +288,7 @@ pub mod ddc_bucket { cluster_id: ClusterId, #[ink(topic)] node_key: NodeKey, + v_nodes: Vec, } #[ink(event)] @@ -361,6 +362,7 @@ pub mod ddc_bucket { cluster_id: ClusterId, #[ink(topic)] node_key: NodeKey, + v_nodes: Vec, } /// A vnode was re-assigned to new node. @@ -371,6 +373,7 @@ pub mod ddc_bucket { cluster_id: ClusterId, #[ink(topic)] node_key: NodeKey, + v_nodes: Vec, } /// Some resources were reserved for the cluster from the nodes. diff --git a/scripts/sdk/src/bucket/ddcBucket.js b/scripts/sdk/src/bucket/ddcBucket.js index 592c7a48..2df8a158 100644 --- a/scripts/sdk/src/bucket/ddcBucket.js +++ b/scripts/sdk/src/bucket/ddcBucket.js @@ -75,7 +75,8 @@ function findClusterNodeAddedEvent(events) { const event = findEvent(events, "ClusterNodeAdded"); const clusterId = _.get(event, "args[0]").toNumber(); const nodeKey = _.get(event, "args[1]").toString(); - return { nodeKey, clusterId }; + const vNodes = _.get(event, "args[2]").toString(); + return { nodeKey, clusterId, vNodes }; } function findClusterCdnNodeAddedEvent(events) { From 7c21fedec31ac6b9405383d06a0c289cf27c2fa3 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 3 Jul 2023 21:13:51 +0200 Subject: [PATCH 84/89] fix(cluster): restrict cdn revenues endpoint --- bucket/ddc_bucket/cluster/entity.rs | 4 ++-- bucket/ddc_bucket/cluster/messages.rs | 3 ++- bucket/ddc_bucket/perm/entity.rs | 1 + bucket/ddc_bucket/perm/messages.rs | 10 +++++++++- bucket/ddc_bucket/tests/test_cluster.rs | 4 ++++ bucket/lib.rs | 1 + 6 files changed, 19 insertions(+), 4 deletions(-) diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index 1638fd6f..d8c737f2 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -72,9 +72,9 @@ impl Cluster { cluster_params: ClusterParams::default(), nodes_keys: Vec::new(), resource_per_v_node, - resource_used: 0, + resource_used: Resource::from(0u32), revenues: Cash(0), - total_rent: 0, + total_rent: Balance::from(0u128), cdn_nodes_keys: Vec::new(), cdn_usd_per_gb: CDN_USD_PER_GB, // setting initially to 1 cent per GB cdn_revenues: Cash(0), diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 1545a541..9e5b2ff4 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -562,8 +562,9 @@ impl DdcBucket { aggregates_buckets: Vec<(BucketId, Resource)>, era: u64 ) -> Result<()> { - let mut cluster = self.clusters.get(cluster_id)?; + self.only_validator()?; + let mut cluster = self.clusters.get(cluster_id)?; let mut cluster_payment = 0; let mut _undistributed_payment_accounts = 0; diff --git a/bucket/ddc_bucket/perm/entity.rs b/bucket/ddc_bucket/perm/entity.rs index d5bceb25..b5208fe6 100644 --- a/bucket/ddc_bucket/perm/entity.rs +++ b/bucket/ddc_bucket/perm/entity.rs @@ -10,4 +10,5 @@ pub enum Permission { ClusterManagerTrustedBy(AccountId), SetExchangeRate, SuperAdmin, + Validator } diff --git a/bucket/ddc_bucket/perm/messages.rs b/bucket/ddc_bucket/perm/messages.rs index 9c34759f..3d9c3b78 100644 --- a/bucket/ddc_bucket/perm/messages.rs +++ b/bucket/ddc_bucket/perm/messages.rs @@ -31,5 +31,13 @@ impl DdcBucket { .then(|| caller) .ok_or(OnlyTrustedClusterManager) } - + + pub fn only_validator(&self) -> Result { + let caller = Self::env().caller(); + let perm = Permission::Validator; + self.perms.has_permission(caller, perm) + .then(|| caller) + .ok_or(OnlyValidator) + } + } diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 87d67319..94584e56 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -1874,6 +1874,10 @@ fn cluster_distribute_cdn_revenue_ok() { let account0_before_putting = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); println!("Before putting revenue: {:?}", account0_before_putting); + let permission = Permission::Validator; + set_caller(admin_id()); + ctx.contract.admin_grant_permission(admin_id(), permission)?; + ctx.contract.cluster_put_cdn_revenue( ctx.cluster_id, vec![(ctx.provider_id0, 1000), (ctx.provider_id0, 541643)], diff --git a/bucket/lib.rs b/bucket/lib.rs index d60ffa8b..7f34bdac 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -1759,6 +1759,7 @@ pub mod ddc_bucket { OnlyCdnNodeProvider, OnlyClusterManager, OnlyTrustedClusterManager, + OnlyValidator, OnlySuperAdmin, OnlyClusterManagerOrNodeProvider, OnlyClusterManagerOrCdnNodeProvider, From ac6b0c8b7e48646f8c62f5deae3c2edeba118629 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 3 Jul 2023 22:55:00 +0200 Subject: [PATCH 85/89] chore(lib): ddc nft registry contract is removed; deployment scripts fixed --- Cargo.lock | 21 - Cargo.toml | 1 - Dockerfile | 41 -- README.md | 9 +- bucket/README.md | 3 +- build-and-deploy.sh | 5 +- ddc_nft_registry/Cargo.toml | 66 --- .../ddc_nft_registry/attachment/entity.rs | 38 -- .../ddc_nft_registry/attachment/messages.rs | 28 - .../ddc_nft_registry/attachment/mod.rs | 5 - .../ddc_nft_registry/attachment/store.rs | 39 -- .../ddc_nft_registry/cash/entity.rs | 79 --- .../ddc_nft_registry/cash/messages.rs | 19 - ddc_nft_registry/ddc_nft_registry/cash/mod.rs | 2 - .../ddc_nft_registry/contract_fee.rs | 37 -- .../ddc_nft_registry/tests/env_utils.rs | 63 --- .../ddc_nft_registry/tests/mod.rs | 3 - .../ddc_nft_registry/tests/test_contract.rs | 127 ----- ddc_nft_registry/lib.rs | 108 ---- scripts/README.md | 25 +- scripts/ddc-setup/ddcSetup.js | 32 +- scripts/deployment/ddcBucketDeploy.js | 7 +- scripts/deployment/ddcNftRegistryDeploy.js | 15 - scripts/deployment/deploy.js | 6 +- scripts/examples/ddcBucketDemo.js | 27 +- scripts/examples/ddcBucketPrint.js | 7 +- scripts/examples/ddcNftRegistryDemo.js | 77 --- scripts/package.json | 8 +- scripts/sdk/src/abi/ddc_bucket.json | 481 ++++++++++++------ scripts/sdk/src/abi/ddc_nft_registry.json | 384 -------------- scripts/sdk/src/config/index.js | 10 +- scripts/sdk/src/ddcNftRegistry/nftRegistry.js | 21 - scripts/sdk/src/deploymentRegistry.js | 17 +- scripts/sdk/src/index.js | 1 - 34 files changed, 371 insertions(+), 1441 deletions(-) delete mode 100644 Dockerfile delete mode 100755 ddc_nft_registry/Cargo.toml delete mode 100644 ddc_nft_registry/ddc_nft_registry/attachment/entity.rs delete mode 100644 ddc_nft_registry/ddc_nft_registry/attachment/messages.rs delete mode 100644 ddc_nft_registry/ddc_nft_registry/attachment/mod.rs delete mode 100644 ddc_nft_registry/ddc_nft_registry/attachment/store.rs delete mode 100644 ddc_nft_registry/ddc_nft_registry/cash/entity.rs delete mode 100644 ddc_nft_registry/ddc_nft_registry/cash/messages.rs delete mode 100644 ddc_nft_registry/ddc_nft_registry/cash/mod.rs delete mode 100644 ddc_nft_registry/ddc_nft_registry/contract_fee.rs delete mode 100644 ddc_nft_registry/ddc_nft_registry/tests/env_utils.rs delete mode 100644 ddc_nft_registry/ddc_nft_registry/tests/mod.rs delete mode 100644 ddc_nft_registry/ddc_nft_registry/tests/test_contract.rs delete mode 100755 ddc_nft_registry/lib.rs delete mode 100644 scripts/deployment/ddcNftRegistryDeploy.js delete mode 100644 scripts/examples/ddcNftRegistryDemo.js delete mode 100644 scripts/sdk/src/abi/ddc_nft_registry.json delete mode 100644 scripts/sdk/src/ddcNftRegistry/nftRegistry.js diff --git a/Cargo.lock b/Cargo.lock index d33dd0d0..1da8286f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -117,27 +117,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "ddc_nft_registry" -version = "0.5.2" -dependencies = [ - "ink_allocator", - "ink_env", - "ink_lang", - "ink_lang_codegen", - "ink_lang_ir", - "ink_lang_macro", - "ink_metadata", - "ink_prelude", - "ink_primitives", - "ink_storage", - "ink_storage_derive", - "parity-scale-codec", - "scale-info", - "serde", - "serde_json", -] - [[package]] name = "derive_more" version = "0.99.17" diff --git a/Cargo.toml b/Cargo.toml index 941c7156..da6d1c5c 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,6 @@ resolver = "2" members = [ "bucket", - "ddc_nft_registry", ] # Needed until https://github.com/paritytech/ink/issues/364 is resolved. diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index de614daf..00000000 --- a/Dockerfile +++ /dev/null @@ -1,41 +0,0 @@ -ARG VCS_REF=master -ARG BUILD_DATE="" -ARG REGISTRY_PATH=docker.io/paritytech - -FROM ${REGISTRY_PATH}/base-ci-linux:latest - -ARG RUST_NIGHTLY="2023-03-21" - -WORKDIR /builds - -RUN apt-get update && apt-get upgrade - -RUN apt-get install -y binaryen - -RUN rustup target add wasm32-unknown-unknown --toolchain stable && \ - rustup component add rust-src --toolchain stable && \ - rustup default stable && \ - - # We also use the nightly toolchain for linting. We perform checks using RustFmt, and - # Cargo Clippy. - # - # Note that we pin the nightly toolchain since it often creates breaking changes during - # the RustFmt and Clippy stages of the CI. - rustup toolchain install nightly-${RUST_NIGHTLY} --target wasm32-unknown-unknown \ - --profile minimal --component rustfmt clippy rust-src && \ - - # Alias pinned toolchain as nightly, otherwise it appears as though we - # don't have a nightly toolchain (i.e rustc +nightly --version is empty) - ln -s "/usr/local/rustup/toolchains/nightly-${RUST_NIGHTLY}-x86_64-unknown-linux-gnu" \ - /usr/local/rustup/toolchains/nightly-x86_64-unknown-linux-gnu && \ - - # `cargo-dylint` and `dylint-link` are dependencies needed to run `cargo-contract`. - cargo install cargo-dylint dylint-link && \ - - # Install the latest `cargo-contract` - cargo install cargo-contract@1.5.0 && \ - - # apt clean up - apt-get autoremove -y && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/* diff --git a/README.md b/README.md index e136a802..39fdae49 100644 --- a/README.md +++ b/README.md @@ -25,19 +25,14 @@ cargo install cargo-contract --version 1.5.0 --force --locked brew install binaryen # For Debian\Ubuntu: # apt-get install binaryen - -# Install the documentation generator -git clone https://github.com/Cerebellum-Network/ink-doc-gen.git -cd ink-doc-gen && git checkout v0.1.0 && yarn ``` ## Building ```bash -# Build DDC Bucket and DDC NFT Registry contracts +# Build DDC Bucket contract cargo +nightly-2023-02-07 test && -cargo +nightly-2023-02-07 contract build --release --manifest-path bucket/Cargo.toml && -cargo +nightly-2023-02-07 contract build --release --manifest-path ddc_nft_registry/Cargo.toml +cargo +nightly-2023-02-07 contract build --release --manifest-path bucket/Cargo.toml ``` Note: if you are encountering errors during build process, they may be related to your specific processor's architecture. If this is the case, try out the *Instalation using Docker image* option, [described in the official docs](https://github.com/paritytech/cargo-contract#installation-using-docker-image) diff --git a/bucket/README.md b/bucket/README.md index d29ce01a..6b954961 100644 --- a/bucket/README.md +++ b/bucket/README.md @@ -67,10 +67,9 @@ A cluster may be managed by a trusted party using an external account, or by a s - Providers registers Nodes. node_create - Providers signal trust to a Manager. - node_trust_manager + grant_trusted_manager_permission - Manager creates a Cluster and reserve some capacity from Nodes. cluster_create - cluster_reserve_resource - Owner creates a Bucket in a Cluster. bucket_create - Owner deposits some funds. diff --git a/build-and-deploy.sh b/build-and-deploy.sh index 48107b65..83316aae 100755 --- a/build-and-deploy.sh +++ b/build-and-deploy.sh @@ -5,10 +5,7 @@ set -eu cargo +nightly-2023-02-07 test cargo +nightly-2023-02-07 contract build --release --manifest-path bucket/Cargo.toml -# cargo +nightly-2023-02-07 contract build --release --manifest-path ddc_nft_registry/Cargo.toml cp target/ink/ddc_bucket/metadata.json scripts/sdk/src/abi/ddc_bucket.json -# cp target/ink/ddc_nft_registry/metadata.json scripts/sdk/src/abi/ddc_nft_registry.json -# yarn --cwd scripts deploy-ddc-bucket -# yarn --cwd scripts deploy-ddc-nft-registry \ No newline at end of file +yarn --cwd scripts deploy-ddc-bucket \ No newline at end of file diff --git a/ddc_nft_registry/Cargo.toml b/ddc_nft_registry/Cargo.toml deleted file mode 100755 index f3248ff8..00000000 --- a/ddc_nft_registry/Cargo.toml +++ /dev/null @@ -1,66 +0,0 @@ -[package] -name = "ddc_nft_registry" -version = "0.5.2" -authors = ["Aurélien Nicolas ", "Anton Volk "] -edition = "2021" - -[dependencies] -scale = { package = "parity-scale-codec", version = "=3.1.2", default-features = false, features = ["derive"] } -scale-info = { version = "=2.0.1", default-features = false, features = ["derive"], optional = true } - -ink_primitives = { version = "3.4.0", default-features = false } -ink_metadata = { version = "3.4.0", default-features = false, features = ["derive"], optional = true } -ink_env = { version = "3.4.0", default-features = false } -ink_storage = { version = "3.4.0", default-features = false } -ink_lang = { version = "3.4.0", default-features = false } -ink_prelude = { version = "3.4.0", default-features = false } - -# Transitive dependencies necessary to fix the version. -ink_allocator = { version = "3.4.0", default-features = false, optional = true } -ink_lang_codegen = { version = "3.4.0", default-features = false, optional = true } -ink_storage_derive = { version = "3.4.0", default-features = false, optional = true } -ink_lang_ir = { version = "3.4.0", default-features = false, optional = true } -ink_lang_macro = { version = "3.4.0", default-features = false, optional = true } - -serde = { version = "1.0.136", optional = true } -serde_json = { version = "1.0.79", optional = true } - -[lib] -name = "ddc_nft_registry" -path = "lib.rs" -crate-type = [ - # Used for normal contract Wasm blobs. - "cdylib", - # Used for ABI generation. - "rlib", -] - -[features] -default = ["std"] -std = [ - "scale/std", - "scale-info/std", - "ink_metadata/std", - "ink_env/std", - "ink_storage/std", - "ink_primitives/std", - "ink_prelude/std", - # Transitive dependencies. - "ink_allocator/std", - "ink_lang_codegen/std", - #"ink_storage_derive/std", - "ink_lang_ir/std", - "ink_lang_macro/std", - - # For tests - "serde", - "serde_json", -] -ink-as-dependency = [] - - -# Needed until https://github.com/paritytech/ink/issues/364 is resolved. -[profile.release] -overflow-checks = false -[profile.dev] -overflow-checks = false diff --git a/ddc_nft_registry/ddc_nft_registry/attachment/entity.rs b/ddc_nft_registry/ddc_nft_registry/attachment/entity.rs deleted file mode 100644 index c9fdc792..00000000 --- a/ddc_nft_registry/ddc_nft_registry/attachment/entity.rs +++ /dev/null @@ -1,38 +0,0 @@ -//! The data structure of Attachments. - -use ink_storage::traits::{PackedLayout, SpreadLayout}; -use scale::{Decode, Encode}; -use ink_prelude::string::String; -use crate::ddc_nft_registry::contract_fee::{SIZE_ACCOUNT_ID, SIZE_HASHMAP, SIZE_PER_RECORD, SIZE_VEC}; -use crate::ddc_nft_registry::AccountId; - -pub type NftId = String; -pub type AssetId = String; -pub type Proof = String; - -#[derive(Clone, PartialEq, Encode, Decode, SpreadLayout, PackedLayout)] -#[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] -pub struct Attachment { - pub reporter_id: AccountId, - pub nft_id: NftId, - pub asset_id: AssetId, - pub proof: Proof, -} - -impl Attachment { - pub fn record_size(&self) -> usize { - return SIZE_PER_RECORD + SIZE_HASHMAP // Map overhead - + SIZE_VEC // Key string - + SIZE_VEC * 3 // Value strings - + SIZE_ACCOUNT_ID // Reporter ID - + self.nft_id.len() * 2 // NFT ID in key and in value - + self.asset_id.len() // Asset ID - + self.proof.len(); // Proof data - } -} - -#[derive(Clone, PartialEq, Encode, Decode)] -#[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] -pub struct AttachmentStatus { - pub attachment: Attachment, -} diff --git a/ddc_nft_registry/ddc_nft_registry/attachment/messages.rs b/ddc_nft_registry/ddc_nft_registry/attachment/messages.rs deleted file mode 100644 index bdfc9a87..00000000 --- a/ddc_nft_registry/ddc_nft_registry/attachment/messages.rs +++ /dev/null @@ -1,28 +0,0 @@ -//! The public interface to manage Attachments. - -use ink_lang::codegen::{EmitEvent, StaticEnv}; - -use crate::ddc_nft_registry::{Attach, DdcNftRegistry, Result}; -use crate::ddc_nft_registry::attachment::entity::{AssetId, AttachmentStatus, NftId, Proof}; - -impl DdcNftRegistry { - pub fn message_attach(&mut self, nft_id: NftId, asset_id: AssetId, proof: Proof) -> Result<()> { - let reporter_id = Self::env().caller(); - let attachment = self.attachments.create(reporter_id, nft_id, asset_id, proof)?; - Self::capture_fee_and_refund(attachment.record_size())?; - Self::env().emit_event(Attach { reporter_id, nft_id: attachment.nft_id, asset_id: attachment.asset_id, proof: attachment.proof }); - Ok(()) - } - - pub fn message_report(&mut self, nft_id: NftId, asset_id: AssetId, proof: Proof) -> Result<()> { - let reporter_id = Self::env().caller(); - Self::env().emit_event(Attach { reporter_id, nft_id, asset_id, proof }); - Ok(()) - } - - pub fn message_get_by_nft_id(&mut self, nft_id: NftId) -> Result { - let attachment = self.attachments.get_by_nft_id(nft_id)?; - Ok(AttachmentStatus { attachment }) - } - -} diff --git a/ddc_nft_registry/ddc_nft_registry/attachment/mod.rs b/ddc_nft_registry/ddc_nft_registry/attachment/mod.rs deleted file mode 100644 index bdb87cee..00000000 --- a/ddc_nft_registry/ddc_nft_registry/attachment/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! Attachment management. - -pub mod messages; -pub mod entity; -pub mod store; diff --git a/ddc_nft_registry/ddc_nft_registry/attachment/store.rs b/ddc_nft_registry/ddc_nft_registry/attachment/store.rs deleted file mode 100644 index 0353050f..00000000 --- a/ddc_nft_registry/ddc_nft_registry/attachment/store.rs +++ /dev/null @@ -1,39 +0,0 @@ -//! The store to create and access Attachments. - -use ink_storage::Mapping; -use ink_storage::traits::{SpreadAllocate, SpreadLayout, StorageLayout}; - -use crate::ddc_nft_registry::{AccountId, Error, Error::*}; -use crate::ddc_nft_registry::attachment::entity::{AssetId, NftId, Proof}; - -use super::entity::Attachment; - -#[derive(SpreadAllocate, SpreadLayout, Default)] -#[cfg_attr(feature = "std", derive(StorageLayout, Debug))] -pub struct AttachmentStore(pub Mapping); - -impl AttachmentStore { - #[must_use] - pub fn create(&mut self, reporter_id: AccountId, nft_id: NftId, asset_id: AssetId, proof: Proof) -> Result { - let attachment = Attachment { - reporter_id, - nft_id, - asset_id, - proof, - }; - - // If exists, check that this is the same reporter. - if let Some(previous) = self.0.get(&attachment.nft_id) { - if previous.reporter_id != reporter_id { - return Err(UnauthorizedUpdate); - } - } - - self.0.insert(attachment.nft_id.clone(), &attachment); - Ok(attachment) - } - - pub fn get_by_nft_id(&mut self, nft_id: NftId) -> Result { - return self.0.get(&nft_id).map(|a| a.clone()).ok_or(AttachmentDoesNotExist); - } -} diff --git a/ddc_nft_registry/ddc_nft_registry/cash/entity.rs b/ddc_nft_registry/ddc_nft_registry/cash/entity.rs deleted file mode 100644 index 2cc4b479..00000000 --- a/ddc_nft_registry/ddc_nft_registry/cash/entity.rs +++ /dev/null @@ -1,79 +0,0 @@ -//! Cash and Payable represent money and debt. -//! -//! These data structures facilitate the correctness of money-related calculations using the Rust type system. - -use ink_storage::traits::{PackedLayout, SpreadLayout}; -use scale::{Decode, Encode}; - -use crate::ddc_nft_registry::{Balance, InsufficientBalance, Result}; - -// TODO: remove Clone. -/// Cash represents some value that was taken from someone, and that must be credited to someone. -#[must_use] -#[derive(Clone, PartialEq, Encode, Decode, SpreadLayout, PackedLayout)] -#[cfg_attr(feature = "std", derive(Debug))] -pub struct Cash(pub Balance); - -/// Payable represents some value that was credited to someone, and that must be paid by someone. -/// Payable must be covered by Cash at all times to guarantee the balance of the contract. -#[must_use] -#[derive(PartialEq, Encode, Decode, SpreadLayout, PackedLayout)] -#[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] -pub struct Payable(pub Balance); - -impl Cash { - pub fn borrow_payable_cash(amount: Balance) -> (Payable, Cash) { - (Payable(amount), Cash(amount)) - } - - #[must_use] - pub fn consume(self) -> Balance { self.0 } - - pub fn peek(&self) -> Balance { self.0 } - - pub fn increase(&mut self, cash: Cash) { - self.0 += cash.consume(); - } - - pub fn pay(&mut self, payable: Payable) -> Result<()> { - if self.peek() >= payable.peek() { - self.pay_unchecked(payable); - Ok(()) - } else { - Err(InsufficientBalance) - } - } - - pub fn pay_unchecked(&mut self, payable: Payable) { - self.0 -= payable.consume(); - } -} - -impl Payable { - pub fn new(amount: Balance) -> Self { - Self(amount) - } - - #[must_use] - pub fn consume(self) -> Balance { self.0 } - - pub fn peek(&self) -> Balance { self.0 } -} - -// Implement TypeInfo with a field "value" to work with polkadot.js. -#[cfg(feature = "std")] -impl ::scale_info::TypeInfo for Cash { - type Identity = Self; - fn type_info() -> ::scale_info::Type { - ::scale_info::Type::builder() - .path(::scale_info::Path::new( - "Cash", - "ddc_bucket::ddc_bucket::cash", - )) - .type_params([]) - .composite( - ::scale_info::build::Fields::named() - .field(|f| f.ty::().name("value").type_name("Balance")) - ) - } -} diff --git a/ddc_nft_registry/ddc_nft_registry/cash/messages.rs b/ddc_nft_registry/ddc_nft_registry/cash/messages.rs deleted file mode 100644 index 631fbf7b..00000000 --- a/ddc_nft_registry/ddc_nft_registry/cash/messages.rs +++ /dev/null @@ -1,19 +0,0 @@ -use ink_lang::codegen::StaticEnv; - -use crate::ddc_nft_registry::{AccountId, DdcNftRegistry, Result}; - -use super::entity::Cash; - -impl DdcNftRegistry { - pub fn receive_cash() -> Cash { - Cash(Self::env().transferred_value()) - } - - pub fn send_cash(destination: AccountId, cash: Cash) -> Result<()> { - if cash.peek() == 0 { return Ok(()); } - match Self::env().transfer(destination, cash.consume()) { - Err(_e) => panic!("Transfer failed"), // Err(Error::TransferFailed), - Ok(_v) => Ok(()), - } - } -} diff --git a/ddc_nft_registry/ddc_nft_registry/cash/mod.rs b/ddc_nft_registry/ddc_nft_registry/cash/mod.rs deleted file mode 100644 index 065d9338..00000000 --- a/ddc_nft_registry/ddc_nft_registry/cash/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod entity; -pub mod messages; diff --git a/ddc_nft_registry/ddc_nft_registry/contract_fee.rs b/ddc_nft_registry/ddc_nft_registry/contract_fee.rs deleted file mode 100644 index e92c73d6..00000000 --- a/ddc_nft_registry/ddc_nft_registry/contract_fee.rs +++ /dev/null @@ -1,37 +0,0 @@ -//! This module captures fees necessary to pay for the storage of the contract state. - -use ink_lang::codegen::StaticEnv; - -use crate::ddc_nft_registry::{Balance, DdcNftRegistry, Result, TOKEN}; -use crate::ddc_nft_registry::cash::entity::Payable; - -pub const FEE_PER_BYTE: Balance = TOKEN / 100; - -/// The minimum size assumed for a new object to cover the overhead of storage keys, -/// in addition to the size of the object itself. -pub const SIZE_PER_RECORD: usize = 32; - -/// The size to cover the overhead of HashMap. -pub const SIZE_HASHMAP: usize = 32; - -pub const SIZE_ACCOUNT_ID: usize = 32; -pub const SIZE_NFT_ID: usize = 8 + 20 + 8; -pub const SIZE_PROOF: usize = 20; -pub const SIZE_VEC: usize = 4; -pub const SIZE_BALANCE: usize = 8; -pub const SIZE_INDEX: usize = 4; -pub const SIZE_RESOURCE: usize = 4; - -impl DdcNftRegistry { - pub fn capture_fee_and_refund(record_size: usize) -> Result<()> { - let mut received_value = Self::receive_cash(); - let fee = calculate_contract_fee(record_size); - received_value.pay(fee)?; - let caller = Self::env().caller(); - Self::send_cash(caller, received_value) - } -} - -pub fn calculate_contract_fee(record_size: usize) -> Payable { - Payable::new(FEE_PER_BYTE * record_size as Balance) -} diff --git a/ddc_nft_registry/ddc_nft_registry/tests/env_utils.rs b/ddc_nft_registry/ddc_nft_registry/tests/env_utils.rs deleted file mode 100644 index cc5cfd32..00000000 --- a/ddc_nft_registry/ddc_nft_registry/tests/env_utils.rs +++ /dev/null @@ -1,63 +0,0 @@ -#![allow(unused_variables, dead_code)] - -pub use ink_env::{ - call, - DefaultEnvironment, - test, - test::{advance_block, default_accounts, DefaultAccounts, recorded_events}, -}; -use scale::Decode; - -use crate::ddc_nft_registry::*; - -pub type Event = ::Type; - -/// Recommended contract fee for all operations with reasonable data amounts. -pub const CONTRACT_FEE_LIMIT: Balance = 10 * TOKEN; - -pub fn get_accounts() -> DefaultAccounts { - test::default_accounts::() -} - -pub fn set_caller_value(account: AccountId, value: Balance) { - set_caller(account); - set_value(value); -} - -pub fn set_value(value: Balance) { - test::set_value_transferred::(value); -} - -pub fn set_callee(account: AccountId) { - test::set_callee::(account); -} - -pub fn set_caller(account: AccountId) { - test::set_caller::(account); -} - -pub fn balance_of(account: AccountId) -> Balance { - test::get_account_balance::(account).unwrap() -} - -pub fn set_balance(account: AccountId, balance: Balance) { - test::set_account_balance::(account, balance); -} - -pub fn decode_event(event: &ink_env::test::EmittedEvent) -> Event { - ::decode(&mut &event.data[..]) - .expect("encountered invalid contract event data buffer") -} - -pub fn get_events() -> Vec { - let raw_events = recorded_events().collect::>(); - raw_events.iter().map(decode_event).collect() -} - -pub fn admin_id() -> AccountId { - get_accounts().alice -} - -pub fn contract_id() -> AccountId { - AccountId::from([0x09; 32]) -} diff --git a/ddc_nft_registry/ddc_nft_registry/tests/mod.rs b/ddc_nft_registry/ddc_nft_registry/tests/mod.rs deleted file mode 100644 index db6dc403..00000000 --- a/ddc_nft_registry/ddc_nft_registry/tests/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod env_utils; - -mod test_contract; diff --git a/ddc_nft_registry/ddc_nft_registry/tests/test_contract.rs b/ddc_nft_registry/ddc_nft_registry/tests/test_contract.rs deleted file mode 100644 index c155e991..00000000 --- a/ddc_nft_registry/ddc_nft_registry/tests/test_contract.rs +++ /dev/null @@ -1,127 +0,0 @@ -use ink_lang as ink; - -use crate::ddc_nft_registry::*; - -use super::env_utils::*; - -fn setup() -> DdcNftRegistry { - set_caller(admin_id()); - set_callee(contract_id()); - let contract = DdcNftRegistry::new(); - set_balance(contract_id(), 10); - contract -} - -#[ink::test] -fn attach_works() { - let mut contract = setup(); - - set_balance(get_accounts().alice, 1000 * TOKEN); - let reporter_id = get_accounts().alice; - let nft_id = "0000000000000030ABCD1234ABCD1234ABCD1234ABCD1234ABCD12340000003132333435"; - let asset_id = "4321DCBA4321DCBA4321DCBA4321DCBA4321DCBA"; - let proof = "certified by cere"; - - // Attach asset_id to nft_id - set_caller_value(reporter_id, 1000 * TOKEN); - contract.attach(nft_id.to_string(), asset_id.to_string(), proof.to_string()); - - // Verify attachment of asset_id to nft_id - let ev = get_events().pop().unwrap(); - assert!(matches!(ev, Event::Attach(ev) if ev == - Attach { - reporter_id, - nft_id: nft_id.to_string(), - asset_id: asset_id.to_string(), - proof: proof.to_string(), - })); - - let attachment_status = contract.get_by_nft_id(nft_id.to_string()); - assert_eq!(attachment_status.attachment.nft_id, nft_id.to_string()); - assert_eq!(attachment_status.attachment.asset_id, asset_id.to_string()); - assert_eq!(attachment_status.attachment.proof, proof.to_string()); - - // Attach different attachment to nft_id - let new_asset_id = "beefbeefbeefbeefbeefbeefbeefbeefbeefbeef"; - set_caller_value(reporter_id, 900 * TOKEN); - contract.attach(nft_id.to_string(), new_asset_id.to_string(), proof.to_string()); - - // Verify attachment of new_asset_id to nft_id - let ev = get_events().pop().unwrap(); - assert!(matches!(ev, Event::Attach(ev) if ev == - Attach { - reporter_id, - nft_id: nft_id.to_string(), - asset_id: new_asset_id.to_string(), - proof: proof.to_string(), - })); - - let new_attachment_status = contract.get_by_nft_id(nft_id.to_string()); - assert_eq!(new_attachment_status.attachment.nft_id, nft_id.to_string()); - assert_eq!(new_attachment_status.attachment.asset_id, new_asset_id.to_string()); - assert_eq!(new_attachment_status.attachment.proof, proof.to_string()); -} - -#[ink::test] -fn reattach_only_owner() { - let mut contract = setup(); - - set_balance(get_accounts().alice, 1000 * TOKEN); - let reporter_id = get_accounts().alice; - let nft_id = "0000000000000030ABCD1234ABCD1234ABCD1234ABCD1234ABCD12340000003132333435"; - let asset_id = "4321DCBA4321DCBA4321DCBA4321DCBA4321DCBA"; - let proof = "certified by cere"; - - // Attach asset_id to nft_id - set_caller_value(reporter_id, 1000 * TOKEN); - contract.attach(nft_id.to_string(), asset_id.to_string(), proof.to_string()); - let attachment_status = contract.get_by_nft_id(nft_id.to_string()); - - // Try to attach a different attachment from another account. - let new_asset_id = "beefbeefbeefbeefbeefbeefbeefbeefbeefbeef"; - let not_reporter_id = get_accounts().bob; - set_caller_value(not_reporter_id, 900 * TOKEN); - let result = contract.message_attach(nft_id.to_string(), new_asset_id.to_string(), proof.to_string()); - assert_eq!(result, Err(UnauthorizedUpdate)); - - // The stored attachment did not change. - let new_attachment_status = contract.get_by_nft_id(nft_id.to_string()); - assert_eq!(new_attachment_status, attachment_status); -} - - -#[ink::test] -fn report_works() { - let mut contract = setup(); - - set_balance(get_accounts().alice, 1000 * TOKEN); - let reporter_id = get_accounts().alice; - let nft_id = "0000000000000030ABCD1234ABCD1234ABCD1234ABCD1234ABCD12340000003132333435"; - let asset_id = "4321DCBA4321DCBA4321DCBA4321DCBA4321DCBA"; - let proof = "certified by cere"; - - // Attach asset_id to nft_id - set_caller_value(reporter_id, 1000 * TOKEN); - contract.attach(nft_id.to_string(), asset_id.to_string(), proof.to_string()); - let attachment_status = contract.get_by_nft_id(nft_id.to_string()); - - // Report (but not attach) a different attachment from another account. - let new_asset_id = "beefbeefbeefbeefbeefbeefbeefbeefbeefbeef"; - let new_reporter_id = get_accounts().bob; - set_caller_value(new_reporter_id, 900 * TOKEN); - contract.report(nft_id.to_string(), new_asset_id.to_string(), proof.to_string()); - - // Verify attachment of new_asset_id to nft_id - let ev = get_events().pop().unwrap(); - assert!(matches!(ev, Event::Attach(ev) if ev == - Attach { - reporter_id: new_reporter_id, - nft_id: nft_id.to_string(), - asset_id: new_asset_id.to_string(), - proof: proof.to_string(), - })); - - // The stored attachment did not change. - let new_attachment_status = contract.get_by_nft_id(nft_id.to_string()); - assert_eq!(new_attachment_status, attachment_status); -} diff --git a/ddc_nft_registry/lib.rs b/ddc_nft_registry/lib.rs deleted file mode 100755 index ad74a858..00000000 --- a/ddc_nft_registry/lib.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! The DDC smart contract implementing bucket-based services. - -#![cfg_attr(not(feature = "std"), no_std)] -#![feature(proc_macro_hygiene)] // for tests in a separate file -#![deny(unused_must_use, unused_variables)] - -use ink_lang as ink; - -#[ink::contract] -pub mod ddc_nft_registry { - use ink_prelude::string::String; - use scale::{Decode, Encode}; - - use Error::*; - - use crate::ddc_nft_registry::attachment::entity::AttachmentStatus; - use crate::ddc_nft_registry::attachment::store::AttachmentStore; - use ink_storage::traits::SpreadAllocate; - - pub mod cash; - pub mod contract_fee; - pub mod attachment; - - // ---- Global state ---- - #[ink(storage)] - #[derive(Default, SpreadAllocate)] - pub struct DdcNftRegistry { - attachments: AttachmentStore, - } - - impl DdcNftRegistry { - #[ink(constructor)] - pub fn new() -> Self { - ink_lang::utils::initialize_contract(|_| {}) - } - } - // ---- End global state ---- - - // ---- Bucket ---- - - #[ink(event)] - #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] - pub struct Attach { - reporter_id: AccountId, - nft_id: String, - asset_id: String, - proof: String, - } - - impl DdcNftRegistry { - /// Report and attach an asset ID to an NFT ID. - /// - /// All attachments are recorded as events. - /// There is absolutely no validation, any account can "attach" some asset ID. - /// Events should be filtered by reporter_id, or by analyzing the proof (not specified here). - /// - /// The latest attachment is also recorded in contract storage. - /// The latest asset ID can be queried from get_by_nft_id. - /// The first reporter for an NFT ID can also update the asset ID. - #[ink(message, payable)] - pub fn attach(&mut self, nft_id: String, asset_id: String, proof: String) { - self.message_attach(nft_id, asset_id, proof).unwrap() - } - - /// Report the attachment of an asset ID to an NFT ID. - /// - /// This is recorded only as a contract event. - /// This can *not* be queried from get_by_nft_id. - /// - /// There is absolutely no validation, any account can "report" some asset ID. - /// Events should be filtered by reporter_id, or by analyzing the proof (not specified here). - #[ink(message, payable)] - pub fn report(&mut self, nft_id: String, asset_id: String, proof: String) { - self.message_report(nft_id, asset_id, proof).unwrap() - } - - #[ink(message)] - pub fn get_by_nft_id(&mut self, nft_id: String) -> AttachmentStatus { - self.message_get_by_nft_id(nft_id).unwrap() - } - } - // ---- End Bucket ---- - - - // ---- Utils ---- - /// One token with 10 decimals. - pub const TOKEN: Balance = 10_000_000_000; - - #[derive(Debug, PartialEq, Eq, Encode, Decode)] - #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] - pub enum Error { - InsufficientBalance, - AttachmentDoesNotExist, - UnauthorizedUpdate, - } - - pub type Result = core::result::Result; - - impl From for ink_env::Error { - fn from(_: Error) -> Self { - ink_env::Error::Unknown - } - } - // ---- End Utils ---- - - #[cfg(test)] - mod tests; -} diff --git a/scripts/README.md b/scripts/README.md index 81fe3d62..3dad84ec 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -6,33 +6,23 @@ Also, check the [config file](./sdk/src/config/index.js), to ensure that you are ## Examples -The [examples](./examples/) folder contains scripts that demonstrate how to properly send transacrions to DDC Bucket and DDC NFT Registry contracts using the [@polkadot/api](https://polkadot.js.org/docs/api/) library. These simple scenarious should help other team members to clarify the business logic flow, and quickly detect issues related to various business constraints and infrastructue constraints (i.e. gas price, attached tokens, method signature, etc.). Scripts should be updated while the contract is evolving to reflect the actual logic. +The [examples](./examples/) folder contains scripts that demonstrate how to properly send transacrions to DDC Bucket contracts using the [@polkadot/api](https://polkadot.js.org/docs/api/) library. These simple scenarious should help other team members to clarify the business logic flow, and quickly detect issues related to various business constraints and infrastructue constraints (i.e. gas price, attached tokens, method signature, etc.). Scripts should be updated while the contract is evolving to reflect the actual logic. #### DDC Bucket scenario Run the script as: ``` -yarn run demo-ddc-bucket +ENV=devnet yarn run demo-ddc-bucket ``` The execution progress will be displayed in the console along with links to explorer that will help you to investigate the details of each transaction -#### DDC NFT Registry scenario - -Run the script as: -``` -yarn run demo-nft-registry -``` - -The execution progress will be displayed in the console along with links to explorer that will help you to investigate the details of each transaction - - #### Display DDC Bucket state Run the script as: ``` -yarn run print-ddc-bucket +ENV=devnet yarn run print-ddc-bucket ``` @@ -52,15 +42,6 @@ yarn run deploy-ddc-bucket Optionally, the command can accept a code hash as the first parameter, and constructor name as the second parameter. In order to use these options, your contract artifacts [must be registered](./sdk/src/deploymentRegistry.js) to retrieve the required metadata from artifacts. -#### DDC NFT Registry deployment - -Run the script as: -``` -yarn run deploy-ddc-nft-registry -``` -Optionally, the command can accept a code hash as the first parameter, and constructor name as the second parameter. In order to use these options, your contract artifacts [must be registered](./sdk/src/deploymentRegistry.js) to retrieve the required metadata from artifacts. - - #### Build and Deploy all contracts To run both building and deployment for all contracts, you can use the [build-and-deploy.sh](./../build-and-deploy.sh) script. diff --git a/scripts/ddc-setup/ddcSetup.js b/scripts/ddc-setup/ddcSetup.js index eb3e99e3..4d6db103 100644 --- a/scripts/ddc-setup/ddcSetup.js +++ b/scripts/ddc-setup/ddcSetup.js @@ -15,20 +15,25 @@ const ddcConfig = require('./ddcConfig.js'); const log = console.log; const DDC_BUCKET_CONTRACT_NAME = config.DDC_BUCKET_CONTRACT_NAME; -const INIT_ENV = process.env.INIT_ENV; +const ENV = process.env.ENV; const SUPERADMIN_MNEMONIC = process.env.SUPERADMIN; -const ddcEnvConfig = ddcConfig[INIT_ENV]; -if (ddcEnvConfig === undefined) { - console.error("Please provide INIT_ENV as one of ", Object.keys(ddcConfig)); +const ddcEnvConfig = ddcConfig[ENV]; +if (!ddcEnvConfig) { + console.error("Please provide ENV as one of ", Object.keys(ddcConfig)); process.exit(-1); } console.log(ddcEnvConfig); +if (!SUPERADMIN_MNEMONIC) { + console.error("Please provide SUPERADMIN seed"); + process.exit(-1); +} + deploymentRegistry.initContract( DDC_BUCKET_CONTRACT_NAME, - INIT_ENV, + ENV, ddcEnvConfig.contract_address ); @@ -40,7 +45,7 @@ async function main() { const sadmin = accountFromUri(SUPERADMIN_MNEMONIC); console.log(`Superadmin: ${sadmin.address}`); - const bucketContract = getContract(DDC_BUCKET_CONTRACT_NAME, INIT_ENV, api); + const bucketContract = getContract(DDC_BUCKET_CONTRACT_NAME, ENV, api); log("Using bucket contract", DDC_BUCKET_CONTRACT_NAME, "at", bucketContract.address.toString()); const txOptions = { @@ -94,7 +99,7 @@ async function main() { const param = JSON.stringify(ddcEnvConfig.storage_node_params[i]); const user = randomAccount(); - fs.appendFileSync('secrets.txt', `${user.address}: ${user.mnemonic} -- ${INIT_ENV} storage ${i}\n`); + fs.appendFileSync('secrets.txt', `${user.address}: ${user.mnemonic} -- ${ENV} storage ${i}\n`); console.log(` node ${i}: address ${user.address}, param ${param}`); const storageNodeKey = user.address; @@ -120,21 +125,14 @@ async function main() { const tx1 = bucketContract.tx.clusterCreate( txOptions, - JSON.stringify(ddcEnvConfig.cluster[key].param) + JSON.stringify(ddcEnvConfig.cluster[key].param), + 100000n ); const result1 = await sendTx(sadmin, tx1); log(getExplorerUrl(result1), "\n"); - const { clusterId } = ddcBucket.findClusterCreatedEvent(result1.contractEvents); + let { clusterId } = ddcBucket.findClusterCreatedEvent(result1.contractEvents || []); clustersIds.push(clusterId); - - const tx2 = bucketContract.tx.clusterReserveResource( - txOptions, - clusterId, - 100000n - ); - const result2 = await sendTx(sadmin, tx2); - log(getExplorerUrl(result2), "\n"); } } diff --git a/scripts/deployment/ddcBucketDeploy.js b/scripts/deployment/ddcBucketDeploy.js index 9868c316..04424abc 100644 --- a/scripts/deployment/ddcBucketDeploy.js +++ b/scripts/deployment/ddcBucketDeploy.js @@ -2,13 +2,10 @@ const { deployContract } = require("./deploy"); const { config } = require("./../sdk"); const log = console.log; +const CODE_HASH = process.env.CODE_HASH || null; async function main() { - const args = process.argv.slice(2); - const codeHash = args.length > 0 ? args[0] : null; - const constructorName = args.length > 1 ? args[1] : "new"; - - await deployContract(config.DDC_BUCKET_CONTRACT_NAME, codeHash, constructorName); + await deployContract(config.DDC_BUCKET_CONTRACT_NAME, CODE_HASH); process.exit(0); } diff --git a/scripts/deployment/ddcNftRegistryDeploy.js b/scripts/deployment/ddcNftRegistryDeploy.js deleted file mode 100644 index 68b30971..00000000 --- a/scripts/deployment/ddcNftRegistryDeploy.js +++ /dev/null @@ -1,15 +0,0 @@ -const { deployContract } = require("./deploy"); -const { config } = require("./../sdk"); -const log = console.log; - - -async function main() { - const args = process.argv.slice(2); - const codeHash = args.length > 0 ? args[0] : null; - const constructorName = args.length > 1 ? args[1] : "new"; - - await deployContract(config.DDC_NFT_REGISTRY_CONTRACT_NAME, codeHash, constructorName); - process.exit(0); -} - -main().then(log, log); diff --git a/scripts/deployment/deploy.js b/scripts/deployment/deploy.js index f4c84976..4c5accd8 100644 --- a/scripts/deployment/deploy.js +++ b/scripts/deployment/deploy.js @@ -15,7 +15,11 @@ const log = console.log; const SEED = config.ACTOR_SEED; -const RPC = config.DEVNET_RPC_ENDPOINT; +const RPC = process.env.ENV == 'devnet' + ? config.DEVNET_RPC_ENDPOINT + : process.env.ENV == 'testnet' + ? config.TESTNET_RPC_ENDPOINT + : config.LOCAL_RPC_ENDPOINT; const deployContract = async ( contractName, diff --git a/scripts/examples/ddcBucketDemo.js b/scripts/examples/ddcBucketDemo.js index 2edcbc6b..cbf86674 100644 --- a/scripts/examples/ddcBucketDemo.js +++ b/scripts/examples/ddcBucketDemo.js @@ -17,7 +17,11 @@ const log = console.log; const BUCKET_CONTRACT_NAME = config.DDC_BUCKET_CONTRACT_NAME; const SEED = config.ACTOR_SEED; -const RPC = config.DEVNET_RPC_ENDPOINT; +const RPC = process.env.ENV == 'devnet' + ? config.DEVNET_RPC_ENDPOINT + : process.env.ENV == 'testnet' + ? config.TESTNET_RPC_ENDPOINT + : config.LOCAL_RPC_ENDPOINT; deploymentRegistry.initDefaultContracts(); @@ -97,9 +101,11 @@ async function main() { { log("Setup a cluster..."); let clusterParams = "{}"; + const resourcePerVNode = 10; const tx = bucketContract.tx.clusterCreate( txOptionsPay, - clusterParams + clusterParams, + resourcePerVNode ); const result = await sendTx(account, tx); @@ -162,23 +168,6 @@ async function main() { log("ClusterCdnNodeAdded", event, "\n"); } - { - log("Reserve some resources for the cluster..."); - const clusterResource = 10; - const tx = bucketContract.tx.clusterReserveResource( - txOptions, - clusterId, - clusterResource - ); - - const result = await sendTx(account, tx); - printGas(result); - log(getExplorerUrl(result)); - const events = printEvents(result); - let event = ddcBucket.findClusterReserveResourceEvent(events); - log("ClusterReserveResource", event, "\n"); - } - { log("Changing Storage node status..."); const tx = bucketContract.tx.clusterSetNodeStatus( diff --git a/scripts/examples/ddcBucketPrint.js b/scripts/examples/ddcBucketPrint.js index 5d6e5530..a24b5e65 100644 --- a/scripts/examples/ddcBucketPrint.js +++ b/scripts/examples/ddcBucketPrint.js @@ -10,7 +10,12 @@ const log = console.log; const CONTRACT_NAME = config.DDC_BUCKET_CONTRACT_NAME; -const RPC = config.DEVNET_RPC_ENDPOINT; +const RPC = process.env.ENV == 'devnet' + ? config.DEVNET_RPC_ENDPOINT + : process.env.ENV == 'testnet' + ? config.TESTNET_RPC_ENDPOINT + : config.LOCAL_RPC_ENDPOINT; + const ACCOUNT_FILTER = null; // get data about all accounts. deploymentRegistry.initDefaultContracts(); diff --git a/scripts/examples/ddcNftRegistryDemo.js b/scripts/examples/ddcNftRegistryDemo.js deleted file mode 100644 index 26c6aa72..00000000 --- a/scripts/examples/ddcNftRegistryDemo.js +++ /dev/null @@ -1,77 +0,0 @@ -const { - connect, - accountFromUri, - sendTx, - getContract, - CERE, - MGAS, - ddcNftRegistry, - lodash: _, - deploymentRegistry, - config -} = require("./../sdk"); - -const log = console.log; - -const NFT_REGISTRY_CONTRACT_NAME = config.DDC_NFT_REGISTRY_CONTRACT_NAME; -const SEED = config.ACTOR_SEED; -const RPC = config.DEVNET_RPC_ENDPOINT; - -deploymentRegistry.initDefaultContracts(); - -async function main() { - const {api, chainName, getExplorerUrl} = await connect(RPC); - log("Connected to blockchain:", chainName); - - const account = accountFromUri(SEED); - log("From account", account.address); - - const txOptions = { - value: 0n, - gasLimit: 200_000n * MGAS, - }; - - const txOptionsPay = { - value: 10n * CERE, - gasLimit: 200_000n * MGAS, - }; - - // NFT registry - const registryContract = getContract(NFT_REGISTRY_CONTRACT_NAME, chainName, api); - log("Using nft registry contract", NFT_REGISTRY_CONTRACT_NAME, "at", registryContract.address.toString()); - - // Test data. - const nftId = "0000000000000030ABCD1234ABCD1234ABCD1234ABCD1234ABCD12340000003132333435"; - const assetId = "ddc:1234"; - const proofVal = "cere_tx"; - - { - log("Attach asset…"); - const tx = registryContract.tx.attach(txOptionsPay, nftId, assetId, proofVal); - - const result = await sendTx(account, tx); - printGas(result); - log(getExplorerUrl(result)); - const events = printEvents(result); - - - const { nft_id, asset_id, proof } = ddcNftRegistry.findCreatedAttachment(events); - log(`New attach: nft_id=${nft_id}, asset_id=${asset_id}, proof=${proof}\n`); - } - - process.exit(0); -} - -function printEvents(result) { - const events = result.contractEvents || []; - //log("EVENTS", JSON.stringify(events, null, 4)); - log(events.length, "events"); - return events; -} - -function printGas(result) { - let gas = _.get(result, "dispatchInfo.weight", 0); - log(parseInt(gas / 1e6), "MGas"); -} - -main().then(log, log); diff --git a/scripts/package.json b/scripts/package.json index 22eab1b1..b54cd421 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -5,11 +5,9 @@ "license": "Apache-2.0", "scripts": { "ensure-deps": "yarn --cwd sdk", - "demo-ddc-bucket": "yarn ensure-deps && node examples/ddcBucketDemo.js", - "demo-nft-registry": "yarn ensure-deps && node examples/ddcNftRegistryDemo.js", + "setup-ddc-bucket": "yarn ensure-deps && node ddc-setup/ddcSetup.js", "deploy-ddc-bucket": "yarn ensure-deps && node deployment/ddcBucketDeploy.js", - "deploy-ddc-nft-registry": "yarn ensure-deps && node deployment/ddcNftRegistryDeploy.js", - "print-ddc-bucket": "yarn ensure-deps && node examples/ddcBucketPrint.js", - "ddc-setup": "yarn ensure-deps && node ddc-setup/ddcSetup.js" + "demo-ddc-bucket": "yarn ensure-deps && node examples/ddcBucketDemo.js", + "print-ddc-bucket": "yarn ensure-deps && node examples/ddcBucketPrint.js" } } \ No newline at end of file diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index 9202e027..6bf64b60 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -1,6 +1,6 @@ { "source": { - "hash": "0xcc988ca917fa8ca03d34e33ee0ce905a8e494ac4d412367588c110ceeb5cd1b3", + "hash": "0x1caf5ce3e145731b738594770e25507ba8c09066f63328d913f96cb72ad1ba5d", "language": "ink! 3.4.0", "compiler": "rustc 1.69.0-nightly" }, @@ -205,7 +205,7 @@ { "docs": [], "indexed": true, - "label": "manager", + "label": "manager_id", "type": { "displayName": [ "AccountId" @@ -251,6 +251,17 @@ ], "type": 9 } + }, + { + "docs": [], + "indexed": false, + "label": "v_nodes", + "type": { + "displayName": [ + "Vec" + ], + "type": 27 + } } ], "docs": [], @@ -486,6 +497,17 @@ ], "type": 9 } + }, + { + "docs": [], + "indexed": false, + "label": "v_nodes", + "type": { + "displayName": [ + "Vec" + ], + "type": 27 + } } ], "docs": [ @@ -506,22 +528,33 @@ "type": 6 } }, + { + "docs": [], + "indexed": true, + "label": "node_key", + "type": { + "displayName": [ + "NodeKey" + ], + "type": 9 + } + }, { "docs": [], "indexed": false, - "label": "resource", + "label": "v_nodes", "type": { "displayName": [ - "Resource" + "Vec" ], - "type": 6 + "type": 27 } } ], "docs": [ - " Some resources were reserved for the cluster from the nodes." + " A vnode was re-assigned to new node." ], - "label": "ClusterReserveResource" + "label": "ClusterNodeReset" }, { "args": [ @@ -538,20 +571,20 @@ }, { "docs": [], - "indexed": true, - "label": "provider_id", + "indexed": false, + "label": "resource", "type": { "displayName": [ - "AccountId" + "Resource" ], - "type": 9 + "type": 6 } } ], "docs": [ - " The share of revenues of a cluster for a provider was distributed." + " Some resources were reserved for the cluster from the nodes." ], - "label": "ClusterDistributeRevenues" + "label": "ClusterReserveResource" }, { "args": [ @@ -569,7 +602,7 @@ { "docs": [], "indexed": true, - "label": "manager", + "label": "provider_id", "type": { "displayName": [ "AccountId" @@ -579,9 +612,9 @@ } ], "docs": [ - " A new cluster was created." + " The share of revenues of a cluster for a provider was distributed." ], - "label": "CdnClusterCreated" + "label": "ClusterDistributeRevenues" }, { "args": [ @@ -608,10 +641,8 @@ } } ], - "docs": [ - " The respective share of revenues of a CDN cluster for a provider was distributed." - ], - "label": "CdnClusterDistributeRevenues" + "docs": [], + "label": "ClusterDistributeCdnRevenues" }, { "args": [ @@ -858,7 +889,7 @@ "displayName": [ "Permission" ], - "type": 74 + "type": 75 } } ], @@ -888,7 +919,7 @@ "displayName": [ "Permission" ], - "type": 74 + "type": 75 } } ], @@ -1515,6 +1546,15 @@ ], "type": 13 } + }, + { + "label": "resource_per_v_node", + "type": { + "displayName": [ + "Resource" + ], + "type": 6 + } } ], "docs": [ @@ -1526,6 +1566,7 @@ " # Parameters", "", " * `cluster_params` - [Cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format.", + " * `resource_per_v_node` - Resource value that will be allocated for every virtual node in the cluster.", "", " # Output", "", @@ -1608,7 +1649,8 @@ " * `NodeDoesNotExist` error if the adding Storage node does not exist.", " * `NodeIsAddedToCluster(ClusterId)` error if the adding Storage node is already added to this or another cluster.", " * `AtLeastOneVNodeHasToBeAssigned(ClusterId, NodeKey)` error if there is a Storage node without any virtual nodes in the cluster.", - " * `VNodesSizeExceedsLimit` error if virtual nodes length exceeds storage capacity." + " * `VNodesSizeExceedsLimit` error if virtual nodes length exceeds storage capacity.", + " * `InsufficientNodeResources` - error if there is not enough resources in a physical node." ], "label": "cluster_add_node", "mutates": true, @@ -1752,6 +1794,78 @@ }, "selector": "0x48194ab1" }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 6 + } + }, + { + "label": "node_key", + "type": { + "displayName": [ + "NodeKey" + ], + "type": 9 + } + }, + { + "label": "new_v_nodes", + "type": { + "displayName": [ + "Vec" + ], + "type": 27 + } + } + ], + "docs": [ + " Reeset a Storage node in the targeting cluster.", + "", + " This endpoint resets virtual nodes on a physical Storage node in the targeting cluster.", + " Virtual nodes determines a token (position) on the ring in terms of Consistent Hashing.", + " The Storage node can be reset in the cluster by cluster manager only.", + "", + " # Parameters", + "", + " * `cluster_id` - ID of the targeting cluster.", + " * `node_key` - Public Key associated with the Storage node.", + " * `new_v_nodes` - List of tokens (positions) related to the Storage node to reset.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `ClusterNodeAdded` event on successful Storage node addition.", + "", + " # Errors", + "", + " * `ClusterDoesNotExist` error if the cluster does not exist.", + " * `OnlyTrustedClusterManager` error if the caller is not a trusted cluster manager.", + " * `NodeDoesNotExist` error if the adding Storage node does not exist.", + " * `NodeIsAddedToCluster(ClusterId)` error if the adding Storage node is already added to this or another cluster.", + " * `AtLeastOneVNodeHasToBeAssigned(ClusterId, NodeKey)` error if there is a Storage node without any virtual nodes in the cluster.", + " * `VNodesSizeExceedsLimit` error if virtual nodes length exceeds storage capacity.", + " * `InsufficientNodeResources` - error if there is not enough resources in a physical node." + ], + "label": "cluster_reset_node", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0xa78b2e19" + }, { "args": [ { @@ -1892,7 +2006,7 @@ "docs": [ " Sets parameters for the targeting cluster.", "", - " This enpoint updates [cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. ", + " This endpoint updates [cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. ", " All cluster parameters must be specified as the endpoint works using SET approach.", "", " # Parameters", @@ -1939,7 +2053,7 @@ "docs": [ " Removes a cluster.", "", - " This enpoint removes the cluster if it does not contain any nodes.", + " This endpoint removes the cluster if it does not contain any nodes.", " Only an empty cluster can be removed.", "", " # Parameters", @@ -2004,7 +2118,7 @@ "docs": [ " Changes Storage node status.", "", - " This enpoint changes Storage node status in a cluster.", + " This endpoint changes Storage node status in a cluster.", "", " # Parameters", "", @@ -2070,7 +2184,7 @@ "docs": [ " Changes CDN node status.", "", - " This enpoint changes CDN node status in a cluster.", + " This endpoint changes CDN node status in a cluster.", "", " # Parameters", "", @@ -2103,6 +2217,66 @@ }, "selector": "0x577027ba" }, + { + "args": [ + { + "label": "cluster_id", + "type": { + "displayName": [ + "ClusterId" + ], + "type": 6 + } + }, + { + "label": "new_resource_per_v_node", + "type": { + "displayName": [ + "Resource" + ], + "type": 6 + } + } + ], + "docs": [ + " Sets the resource used per virual node in cluster.", + "", + " This endpoint sets the resource value that is being used by each virtual node in the cluster.", + " If there are existing virtual nodes in the cluster the resource for its physical nodes will be recalculated.", + "", + " # Parameters", + "", + " * `cluster_id` - ID of the targeting cluster.", + " * `new_resource_per_v_node` - Resource value that will be allocated for every virtual node in the cluster.", + "", + " # Output", + "", + " Returns nothing.", + "", + " # Events", + "", + " * `ClusterNodeReplaced` event on successful virtual node reassignment.", + "", + " # Errors", + "", + " * `ClusterDoesNotExist` error if the cluster does not exist.", + " * `OnlyClusterManager` error if the caller is not the cluster manager.", + " * `NodeDoesNotExist` error if the new Storage node does not exist.", + " * `VNodeIsNotAssignedToNode(ClusterId, VNodeToken)` error if the there is some virtual node that is being reasigned, but this virtual node is not assigned to any physical node.", + " * `InsufficientClusterResources` - error if there is not enough resources in the cluster.", + " * `InsufficientNodeResources` - error if there is not enough resources in a physical node." + ], + "label": "cluster_set_resource_per_v_node", + "mutates": true, + "payable": false, + "returnType": { + "displayName": [ + "Result" + ], + "type": 44 + }, + "selector": "0xbca5ef71" + }, { "args": [ { @@ -2118,7 +2292,7 @@ "docs": [ " Gets a cluster.", "", - " This enpoint gets the targeting cluster along with its parameters, Storage and CDN nodes.", + " This endpoint gets the targeting cluster along with its parameters, Storage and CDN nodes.", "", " # Parameters", "", @@ -2176,7 +2350,7 @@ "docs": [ " Gets a paginated list of clusters.", "", - " This enpoint gets a paginated list of clusters along with their parameters, Storage and CDN nodes.", + " This endpoint gets a paginated list of clusters along with their parameters, Storage and CDN nodes.", " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", " The optimal `limit` depends on the size of params.", "", @@ -2199,43 +2373,6 @@ }, "selector": "0xd9db9d44" }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 6 - } - }, - { - "label": "amount", - "type": { - "displayName": [ - "Resource" - ], - "type": 6 - } - } - ], - "docs": [ - " As manager, reserve more resources for the cluster from the free capacity of nodes.", - "", - " The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes)." - ], - "label": "cluster_reserve_resource", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 44 - }, - "selector": "0xb5e38125" - }, { "args": [ { @@ -2642,7 +2779,7 @@ "docs": [ " Removes a CDN node.", "", - " This enpoint removes the targeting CDN Node if it is not added to some cluster.", + " This endpoint removes the targeting CDN Node if it is not added to some cluster.", " Only a node that is not a member of some cluster can be removed.", "", " # Parameters", @@ -2698,7 +2835,7 @@ "docs": [ " Sets parameters for the targeting CDN node.", "", - " This enpoint updates [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. ", + " This endpoint updates [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. ", " All CDN node parameters must be specified as the endpoint works using SET approach.", "", " # Parameters", @@ -2745,7 +2882,7 @@ "docs": [ " Gets a CDN node.", "", - " This enpoint gets the targeting CDN node along with its parameters.", + " This endpoint gets the targeting CDN node along with its parameters.", "", " # Parameters", "", @@ -2803,7 +2940,7 @@ "docs": [ " Gets a paginated list of CDN nodes.", "", - " This enpoint gets a paginated list of CDN nodes along with their parameters.", + " This endpoint gets a paginated list of CDN nodes along with their parameters.", " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", " The optimal `limit` depends on the size of params.", "", @@ -2917,7 +3054,7 @@ "docs": [ " Removes a Storage node.", "", - " This enpoint removes the targeting Storage Node if it is not added to some cluster.", + " This endpoint removes the targeting Storage Node if it is not added to some cluster.", " Only a node that is not a member of some cluster can be removed.", "", " # Parameters", @@ -2973,7 +3110,7 @@ "docs": [ " Sets parameters for the targeting Storage node.", "", - " This enpoint updates [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. ", + " This endpoint updates [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. ", " All Storage node parameters must be specified as the endpoint works using SET approach.", "", " # Parameters", @@ -3020,7 +3157,7 @@ "docs": [ " Gets a Storage node.", "", - " This enpoint gets the targeting Storage node along with its parameters.", + " This endpoint gets the targeting Storage node along with its parameters.", "", " # Parameters", "", @@ -3078,7 +3215,7 @@ "docs": [ " Gets a paginated list of Storage nodes.", "", - " This enpoint gets a paginated list of Storage nodes along with their parameters.", + " This endpoint gets a paginated list of Storage nodes along with their parameters.", " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", " The optimal `limit` depends on the size of params.", "", @@ -3133,6 +3270,22 @@ }, "selector": "0x07c63885" }, + { + "args": [], + "docs": [ + " Get the Fee Percentage Basis Points that will be charged by the protocol" + ], + "label": "get_network_fee_config", + "mutates": false, + "payable": false, + "returnType": { + "displayName": [ + "NetworkFeeConfig" + ], + "type": 73 + }, + "selector": "0xd1503f07" + }, { "args": [], "docs": [ @@ -3242,7 +3395,7 @@ "displayName": [ "Result" ], - "type": 73 + "type": 74 }, "selector": "0x1d4220fa" }, @@ -3307,14 +3460,14 @@ "displayName": [ "Permission" ], - "type": 74 + "type": 75 } } ], "docs": [ " Checks for permission existence.", "", - " This enpoint checks whether the given account has the given permission.", + " This endpoint checks whether the given account has the given permission.", " Super-admin will always have all permissions.", "", " # Parameters", @@ -3344,7 +3497,7 @@ { "args": [ { - "label": "manager", + "label": "manager_id", "type": { "displayName": [ "AccountId" @@ -3362,7 +3515,7 @@ "", " # Parameters", "", - " * `manager` - cluster manager account.", + " * `manager_id` - cluster manager account.", "", " # Output", "", @@ -3390,7 +3543,7 @@ { "args": [ { - "label": "manager", + "label": "manager_id", "type": { "displayName": [ "AccountId" @@ -3408,7 +3561,7 @@ "", " # Parameters", "", - " * `manager` - cluster manager account.", + " * `manager_id` - cluster manager account.", "", " # Output", "", @@ -3450,7 +3603,7 @@ "displayName": [ "Permission" ], - "type": 74 + "type": 75 } } ], @@ -3504,7 +3657,7 @@ "displayName": [ "Permission" ], - "type": 74 + "type": 75 } } ], @@ -3686,19 +3839,19 @@ { "args": [ { - "label": "config", + "label": "amount", "type": { "displayName": [ - "NetworkFeeConfig" + "Balance" ], - "type": 75 + "type": 12 } } ], "docs": [ - " As SuperAdmin, set the network and cluster fee configuration." + " Pay the revenues accumulated by the protocol" ], - "label": "admin_set_network_fee_config", + "label": "admin_withdraw_protocol_revenues", "mutates": true, "payable": false, "returnType": { @@ -3707,24 +3860,24 @@ ], "type": 44 }, - "selector": "0x14649395" + "selector": "0xa781da48" }, { "args": [ { - "label": "amount", + "label": "config", "type": { "displayName": [ - "u128" + "NetworkFeeConfig" ], - "type": 12 + "type": 73 } } ], "docs": [ - " Pay the revenues accumulated by the protocol" + " As SuperAdmin, set the network and cluster fee configuration." ], - "label": "admin_withdraw_protocol_revenues", + "label": "admin_set_network_fee_config", "mutates": true, "payable": false, "returnType": { @@ -3733,7 +3886,7 @@ ], "type": 44 }, - "selector": "0xa781da48" + "selector": "0x14649395" }, { "args": [ @@ -3741,7 +3894,7 @@ "label": "protocol_fee_bp", "type": { "displayName": [ - "u128" + "BasisPoints" ], "type": 12 } @@ -5432,26 +5585,30 @@ }, { "index": 12, - "name": "OnlySuperAdmin" + "name": "OnlyValidator" }, { "index": 13, - "name": "OnlyClusterManagerOrNodeProvider" + "name": "OnlySuperAdmin" }, { "index": 14, - "name": "OnlyClusterManagerOrCdnNodeProvider" + "name": "OnlyClusterManagerOrNodeProvider" }, { "index": 15, - "name": "Unauthorized" + "name": "OnlyClusterManagerOrCdnNodeProvider" }, { "index": 16, - "name": "ClusterDoesNotExist" + "name": "Unauthorized" }, { "index": 17, + "name": "ClusterDoesNotExist" + }, + { + "index": 18, "name": "ClusterIsNotEmpty" }, { @@ -5461,27 +5618,27 @@ "typeName": "ClusterId" } ], - "index": 18, + "index": 19, "name": "TopologyIsNotCreated" }, { - "index": 19, + "index": 20, "name": "TopologyAlreadyExists" }, { - "index": 20, + "index": 21, "name": "NodesSizeExceedsLimit" }, { - "index": 21, + "index": 22, "name": "CdnNodesSizeExceedsLimit" }, { - "index": 22, + "index": 23, "name": "VNodesSizeExceedsLimit" }, { - "index": 23, + "index": 24, "name": "AccountsSizeExceedsLimit" }, { @@ -5491,7 +5648,7 @@ "typeName": "ClusterId" } ], - "index": 24, + "index": 25, "name": "NodeIsNotAddedToCluster" }, { @@ -5501,7 +5658,7 @@ "typeName": "ClusterId" } ], - "index": 25, + "index": 26, "name": "NodeIsAddedToCluster" }, { @@ -5511,7 +5668,7 @@ "typeName": "ClusterId" } ], - "index": 26, + "index": 27, "name": "CdnNodeIsNotAddedToCluster" }, { @@ -5521,7 +5678,7 @@ "typeName": "ClusterId" } ], - "index": 27, + "index": 28, "name": "CdnNodeIsAddedToCluster" }, { @@ -5531,7 +5688,7 @@ "typeName": "ClusterId" } ], - "index": 28, + "index": 29, "name": "VNodeDoesNotExistsInCluster" }, { @@ -5545,7 +5702,7 @@ "typeName": "VNodeToken" } ], - "index": 29, + "index": 30, "name": "VNodeIsNotAssignedToNode" }, { @@ -5555,7 +5712,7 @@ "typeName": "NodeKey" } ], - "index": 30, + "index": 31, "name": "VNodeIsAlreadyAssignedToNode" }, { @@ -5569,39 +5726,43 @@ "typeName": "NodeKey" } ], - "index": 31, + "index": 32, "name": "AtLeastOneVNodeHasToBeAssigned" }, { - "index": 32, + "index": 33, "name": "NodeProviderIsNotSuperAdmin" }, { - "index": 33, + "index": 34, "name": "CdnNodeOwnerIsNotSuperAdmin" }, { - "index": 34, + "index": 35, "name": "BucketDoesNotExist" }, { - "index": 35, + "index": 36, "name": "BondingPeriodNotFinished" }, { - "index": 36, + "index": 37, "name": "TransferFailed" }, { - "index": 37, + "index": 38, "name": "InsufficientBalance" }, { - "index": 38, - "name": "InsufficientResources" + "index": 39, + "name": "InsufficientNodeResources" }, { - "index": 39, + "index": 40, + "name": "InsufficientClusterResources" + }, + { + "index": 41, "name": "EraSettingFailed" } ] @@ -6350,6 +6511,39 @@ }, { "id": 73, + "type": { + "def": { + "composite": { + "fields": [ + { + "name": "network_fee_bp", + "type": 12, + "typeName": "BasisPoints" + }, + { + "name": "network_fee_destination", + "type": 9, + "typeName": "AccountId" + }, + { + "name": "cluster_management_fee_bp", + "type": 12, + "typeName": "BasisPoints" + } + ] + } + }, + "path": [ + "ddc_bucket", + "ddc_bucket", + "protocol", + "store", + "NetworkFeeConfig" + ] + } + }, + { + "id": 74, "type": { "def": { "variant": { @@ -6391,7 +6585,7 @@ } }, { - "id": 74, + "id": 75, "type": { "def": { "variant": { @@ -6413,6 +6607,10 @@ { "index": 2, "name": "SuperAdmin" + }, + { + "index": 3, + "name": "Validator" } ] } @@ -6425,39 +6623,6 @@ "Permission" ] } - }, - { - "id": 75, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "network_fee_bp", - "type": 12, - "typeName": "BasisPoints" - }, - { - "name": "network_fee_destination", - "type": 9, - "typeName": "AccountId" - }, - { - "name": "cluster_management_fee_bp", - "type": 12, - "typeName": "BasisPoints" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "protocol", - "store", - "NetworkFeeConfig" - ] - } } ] } diff --git a/scripts/sdk/src/abi/ddc_nft_registry.json b/scripts/sdk/src/abi/ddc_nft_registry.json deleted file mode 100644 index c2f45d2d..00000000 --- a/scripts/sdk/src/abi/ddc_nft_registry.json +++ /dev/null @@ -1,384 +0,0 @@ -{ - "source": { - "hash": "0x6c9783a07ddbc3bad9d23f4e8ce41aafa1d2fa509fa4a397c4b21a5ab4e56cbc", - "language": "ink! 3.4.0", - "compiler": "rustc 1.69.0-nightly" - }, - "contract": { - "name": "ddc_nft_registry", - "version": "0.5.2", - "authors": [ - "Aurélien Nicolas ", - "Anton Volk " - ] - }, - "V3": { - "spec": { - "constructors": [ - { - "args": [], - "docs": [], - "label": "new", - "payable": false, - "selector": "0x9bae9d5e" - } - ], - "docs": [], - "events": [ - { - "args": [ - { - "docs": [], - "indexed": false, - "label": "reporter_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 3 - } - }, - { - "docs": [], - "indexed": false, - "label": "nft_id", - "type": { - "displayName": [ - "String" - ], - "type": 1 - } - }, - { - "docs": [], - "indexed": false, - "label": "asset_id", - "type": { - "displayName": [ - "String" - ], - "type": 1 - } - }, - { - "docs": [], - "indexed": false, - "label": "proof", - "type": { - "displayName": [ - "String" - ], - "type": 1 - } - } - ], - "docs": [], - "label": "Attach" - } - ], - "messages": [ - { - "args": [ - { - "label": "nft_id", - "type": { - "displayName": [ - "String" - ], - "type": 1 - } - }, - { - "label": "asset_id", - "type": { - "displayName": [ - "String" - ], - "type": 1 - } - }, - { - "label": "proof", - "type": { - "displayName": [ - "String" - ], - "type": 1 - } - } - ], - "docs": [ - " Report and attach an asset ID to an NFT ID.", - "", - " All attachments are recorded as events.", - " There is absolutely no validation, any account can \"attach\" some asset ID.", - " Events should be filtered by reporter_id, or by analyzing the proof (not specified here).", - "", - " The latest attachment is also recorded in contract storage.", - " The latest asset ID can be queried from get_by_nft_id.", - " The first reporter for an NFT ID can also update the asset ID." - ], - "label": "attach", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x82e05a4c" - }, - { - "args": [ - { - "label": "nft_id", - "type": { - "displayName": [ - "String" - ], - "type": 1 - } - }, - { - "label": "asset_id", - "type": { - "displayName": [ - "String" - ], - "type": 1 - } - }, - { - "label": "proof", - "type": { - "displayName": [ - "String" - ], - "type": 1 - } - } - ], - "docs": [ - " Report the attachment of an asset ID to an NFT ID.", - "", - " This is recorded only as a contract event.", - " This can *not* be queried from get_by_nft_id.", - "", - " There is absolutely no validation, any account can \"report\" some asset ID.", - " Events should be filtered by reporter_id, or by analyzing the proof (not specified here)." - ], - "label": "report", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0xf30f464c" - }, - { - "args": [ - { - "label": "nft_id", - "type": { - "displayName": [ - "String" - ], - "type": 1 - } - } - ], - "docs": [], - "label": "get_by_nft_id", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [ - "AttachmentStatus" - ], - "type": 7 - }, - "selector": "0xb5c41aa2" - } - ] - }, - "storage": { - "struct": { - "fields": [ - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0000000000000000000000000000000000000000000000000000000000000000", - "ty": 0 - } - }, - "name": null - } - ] - } - }, - "name": "attachments" - } - ] - } - }, - "types": [ - { - "id": 0, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 6, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 1 - }, - { - "name": "V", - "type": 2 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 1, - "type": { - "def": { - "primitive": "str" - } - } - }, - { - "id": 2, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "reporter_id", - "type": 3, - "typeName": "AccountId" - }, - { - "name": "nft_id", - "type": 1, - "typeName": "NftId" - }, - { - "name": "asset_id", - "type": 1, - "typeName": "AssetId" - }, - { - "name": "proof", - "type": 1, - "typeName": "Proof" - } - ] - } - }, - "path": [ - "ddc_nft_registry", - "ddc_nft_registry", - "attachment", - "entity", - "Attachment" - ] - } - }, - { - "id": 3, - "type": { - "def": { - "composite": { - "fields": [ - { - "type": 4, - "typeName": "[u8; 32]" - } - ] - } - }, - "path": [ - "ink_env", - "types", - "AccountId" - ] - } - }, - { - "id": 4, - "type": { - "def": { - "array": { - "len": 32, - "type": 5 - } - } - } - }, - { - "id": 5, - "type": { - "def": { - "primitive": "u8" - } - } - }, - { - "id": 6, - "type": { - "def": { - "composite": { - "fields": [ - { - "type": 4, - "typeName": "[u8; 32]" - } - ] - } - }, - "path": [ - "ink_primitives", - "Key" - ] - } - }, - { - "id": 7, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "attachment", - "type": 2, - "typeName": "Attachment" - } - ] - } - }, - "path": [ - "ddc_nft_registry", - "ddc_nft_registry", - "attachment", - "entity", - "AttachmentStatus" - ] - } - } - ] - } -} \ No newline at end of file diff --git a/scripts/sdk/src/config/index.js b/scripts/sdk/src/config/index.js index 978d861b..8c6b577a 100644 --- a/scripts/sdk/src/config/index.js +++ b/scripts/sdk/src/config/index.js @@ -4,21 +4,17 @@ const ACTOR_SEED = "//Alice"; const EXPLORER_URL = "https://explorer.cere.network"; const DDC_BUCKET_CONTRACT_NAME = "ddc_bucket"; -const DDC_NFT_REGISTRY_CONTRACT_NAME = "ddc_nft_registry"; const DEVNET_RPC_ENDPOINT = "wss://archive.devnet.cere.network/ws/"; const DEVNET_DDC_BUCKET_ADDR = "6TCrAcm51jYJwNbEc7zYFBvuBaPru9B1cAkU4PpgoTpTy9VZ"; -const DEVNET_DDC_NFT_REGISTRY_ADDR = "6V1Bf84xDSRWBHjWS3PQCqVJeaJx5imPKGBnnr7WJXUUVGBi"; const DEVNET_CHAIN_NAME = "Cere Devnet"; -const TESTNET_RPC_ENDPOINT = "wss://archive.devnet.cere.network/ws/"; +const TESTNET_RPC_ENDPOINT = "wss://archive.testnet.cere.network/ws/"; const TESTNET_DDC_BUCKET_ADDR = "6TyNotWczZXMaXkF6mJ2cBMS6e1hgu5hFYuTpfg9vtH35gu3"; -const TESTNET_DDC_NFT_REGISTRY_ADDR = "6VFZJT9Kox8iZN4DL27GNFCpfTWHXbDst2WC7jpiJXv36eGR"; const TESTNET_CHAIN_NAME = "Cere Testnet"; const LOCAL_RPC_ENDPOINT = "ws://127.0.0.1:9944/"; const LOCAL_DDC_BUCKET_ADDR = ""; // add your local address -const LOCAL_DDC_NFT_REGISTRY_ADDR = ""; const LOCAL_CHAIN_NAME = "Development"; module.exports = { @@ -26,20 +22,16 @@ module.exports = { EXPLORER_URL, DDC_BUCKET_CONTRACT_NAME, - DDC_NFT_REGISTRY_CONTRACT_NAME, DEVNET_RPC_ENDPOINT, DEVNET_DDC_BUCKET_ADDR, - DEVNET_DDC_NFT_REGISTRY_ADDR, DEVNET_CHAIN_NAME, TESTNET_RPC_ENDPOINT, TESTNET_DDC_BUCKET_ADDR, - TESTNET_DDC_NFT_REGISTRY_ADDR, TESTNET_CHAIN_NAME, LOCAL_RPC_ENDPOINT, LOCAL_DDC_BUCKET_ADDR, - LOCAL_DDC_NFT_REGISTRY_ADDR, LOCAL_CHAIN_NAME } \ No newline at end of file diff --git a/scripts/sdk/src/ddcNftRegistry/nftRegistry.js b/scripts/sdk/src/ddcNftRegistry/nftRegistry.js deleted file mode 100644 index 5d98f618..00000000 --- a/scripts/sdk/src/ddcNftRegistry/nftRegistry.js +++ /dev/null @@ -1,21 +0,0 @@ -const _ = require("lodash"); - - -function findByEventName(events, eventName) { - const event = _.find(events, ["event.identifier", eventName]); - const nft_id = _.get(event, "args[0]"); - const asset_id = _.get(event, "args[1]"); - const proof = _.get(event, "args[2]"); - return { - nft_id, asset_id, proof - }; -} - -function findCreatedAttachment(events) { - return findByEventName(events, "Attach"); -} - - -module.exports = { - findCreatedAttachment, -}; diff --git a/scripts/sdk/src/deploymentRegistry.js b/scripts/sdk/src/deploymentRegistry.js index 96cd965a..a5963326 100644 --- a/scripts/sdk/src/deploymentRegistry.js +++ b/scripts/sdk/src/deploymentRegistry.js @@ -2,7 +2,6 @@ const {registerABI} = require("./abiRegistry.js"); const {registerContract} = require("./contractRegistry.js"); const config = require("./config"); const ddcBucketAbi = require("./abi/ddc_bucket.json"); -const ddcNftRegistryAbi = require("./abi/ddc_nft_registry.json"); function initDefaultContracts() { @@ -26,21 +25,7 @@ function initDefaultContracts() { config.LOCAL_CHAIN_NAME, config.LOCAL_DDC_BUCKET_ADDR ); - - registerABI(config.DDC_NFT_REGISTRY_CONTRACT_NAME, ddcNftRegistryAbi); - - registerContract( - config.DDC_NFT_REGISTRY_CONTRACT_NAME, - config.DEVNET_CHAIN_NAME, - config.DEVNET_DDC_NFT_REGISTRY_ADDR - ); - - registerContract( - config.DDC_NFT_REGISTRY_CONTRACT_NAME, - config.TESTNET_CHAIN_NAME, - config.TESTNET_DDC_NFT_REGISTRY_ADDR - ); - + } function initContract(name, env, address) { diff --git a/scripts/sdk/src/index.js b/scripts/sdk/src/index.js index f8662ea3..86b7ffc9 100644 --- a/scripts/sdk/src/index.js +++ b/scripts/sdk/src/index.js @@ -7,6 +7,5 @@ Object.assign(module.exports, require("./contractRegistry.js")); Object.assign(module.exports, require("./polkadotWrappers.js")); module.exports.ddcBucket = require("./bucket/ddcBucket.js"); module.exports.ddcBucketQuery = require("./bucket/ddcBucketQuery.js"); -module.exports.ddcNftRegistry = require("./ddcNftRegistry/nftRegistry.js"); module.exports.config = require("./config"); module.exports.lodash = require("lodash"); \ No newline at end of file From 08829e8efbb03cba85ea280d19dc8737c9b48dd4 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Mon, 3 Jul 2023 23:36:43 +0200 Subject: [PATCH 86/89] chore(lib): cargo fmt --- bucket/ddc_bucket/account/entity.rs | 30 +- bucket/ddc_bucket/account/messages.rs | 16 +- bucket/ddc_bucket/account/mod.rs | 2 +- bucket/ddc_bucket/account/store.rs | 33 +- bucket/ddc_bucket/admin.rs | 69 +- bucket/ddc_bucket/bucket/entity.rs | 29 +- bucket/ddc_bucket/bucket/messages.rs | 160 +++- bucket/ddc_bucket/bucket/mod.rs | 2 +- bucket/ddc_bucket/bucket/store.rs | 36 +- bucket/ddc_bucket/cash.rs | 27 +- bucket/ddc_bucket/cdn_node/entity.rs | 22 +- bucket/ddc_bucket/cdn_node/messages.rs | 66 +- bucket/ddc_bucket/cdn_node/mod.rs | 2 +- bucket/ddc_bucket/cdn_node/store.rs | 66 +- bucket/ddc_bucket/cluster/entity.rs | 31 +- bucket/ddc_bucket/cluster/messages.rs | 226 ++--- bucket/ddc_bucket/cluster/mod.rs | 2 +- bucket/ddc_bucket/cluster/store.rs | 12 +- bucket/ddc_bucket/committer/messages.rs | 24 +- bucket/ddc_bucket/committer/mod.rs | 4 +- bucket/ddc_bucket/committer/store.rs | 75 +- bucket/ddc_bucket/currency.rs | 18 +- bucket/ddc_bucket/flow.rs | 7 +- bucket/ddc_bucket/node/entity.rs | 22 +- bucket/ddc_bucket/node/messages.rs | 41 +- bucket/ddc_bucket/node/mod.rs | 2 +- bucket/ddc_bucket/node/store.rs | 21 +- bucket/ddc_bucket/perm/entity.rs | 2 +- bucket/ddc_bucket/perm/messages.rs | 31 +- bucket/ddc_bucket/perm/mod.rs | 4 +- bucket/ddc_bucket/perm/store.rs | 6 +- bucket/ddc_bucket/protocol/messages.rs | 8 +- bucket/ddc_bucket/protocol/mod.rs | 2 +- bucket/ddc_bucket/protocol/store.rs | 56 +- bucket/ddc_bucket/schedule.rs | 12 +- bucket/ddc_bucket/tests/env_utils.rs | 5 +- bucket/ddc_bucket/tests/mod.rs | 8 +- bucket/ddc_bucket/tests/setup_utils.rs | 193 ++-- bucket/ddc_bucket/tests/test_account.rs | 13 +- bucket/ddc_bucket/tests/test_admin.rs | 169 ++-- bucket/ddc_bucket/tests/test_bucket.rs | 71 +- bucket/ddc_bucket/tests/test_cdn_node.rs | 100 +- bucket/ddc_bucket/tests/test_cluster.rs | 1107 +++++++++++----------- bucket/ddc_bucket/tests/test_currency.rs | 6 +- bucket/ddc_bucket/tests/test_node.rs | 104 +- bucket/ddc_bucket/topology/messages.rs | 13 +- bucket/ddc_bucket/topology/mod.rs | 2 +- bucket/ddc_bucket/topology/store.rs | 63 +- bucket/lib.rs | 266 +++--- 49 files changed, 1674 insertions(+), 1612 deletions(-) diff --git a/bucket/ddc_bucket/account/entity.rs b/bucket/ddc_bucket/account/entity.rs index 424a1688..32f29d99 100644 --- a/bucket/ddc_bucket/account/entity.rs +++ b/bucket/ddc_bucket/account/entity.rs @@ -3,12 +3,14 @@ use ink_storage::traits::{PackedLayout, SpreadLayout}; use scale::{Decode, Encode}; +use crate::ddc_bucket::currency::{CurrencyConverter, USD}; use crate::ddc_bucket::{ - Balance, cash::{Cash, Payable}, - Error::*, Result, + cash::{Cash, Payable}, schedule::Schedule, + Balance, + Error::*, + Result, }; -use crate::ddc_bucket::currency::{USD, CurrencyConverter}; #[derive(Clone, PartialEq, Encode, Decode, SpreadLayout, PackedLayout)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] @@ -37,16 +39,21 @@ impl Account { self.deposit.increase(cash); } - pub fn bond(&mut self, time_ms: u64, conv: &CurrencyConverter, bond_amount: Balance) -> Result<()> { + pub fn bond( + &mut self, + time_ms: u64, + conv: &CurrencyConverter, + bond_amount: Balance, + ) -> Result<()> { let payable = Payable(bond_amount); if self.get_withdrawable(time_ms, conv) >= payable.peek() { let parsed_payable: u128; - if self.negative.peek() > 0 && payable.peek() >= self.negative.peek() { + if self.negative.peek() > 0 && payable.peek() >= self.negative.peek() { parsed_payable = payable.peek() - self.negative.peek(); self.deposit.pay_unchecked(payable); self.bonded.increase(Cash(parsed_payable)); Ok(()) - } else if self.negative.peek() > 0 && payable.peek() < self.negative.peek(){ + } else if self.negative.peek() > 0 && payable.peek() < self.negative.peek() { Err(InsufficientBalance) } else { let bonded_amount = Cash(payable.peek()); @@ -71,7 +78,12 @@ impl Account { } } - pub fn withdraw(&mut self, time_ms: u64, conv: &CurrencyConverter, payable: Payable) -> Result<()> { + pub fn withdraw( + &mut self, + time_ms: u64, + conv: &CurrencyConverter, + payable: Payable, + ) -> Result<()> { if self.get_withdrawable(time_ms, conv) >= payable.peek() { self.deposit.pay_unchecked(payable); Ok(()) @@ -80,7 +92,7 @@ impl Account { } } - // Add logics when balance is below requested + // Add logics when balance is below requested pub fn withdraw_bonded(&mut self, payable: Payable) -> Result<()> { let remaining_bonded = self.bonded.peek() - self.unbonded_amount.peek(); if remaining_bonded >= payable.peek() { @@ -143,4 +155,4 @@ impl Account { } } -pub const MS_PER_WEEK: u64 = 7 * 24 * 3600 * 1000; \ No newline at end of file +pub const MS_PER_WEEK: u64 = 7 * 24 * 3600 * 1000; diff --git a/bucket/ddc_bucket/account/messages.rs b/bucket/ddc_bucket/account/messages.rs index c5b1bcab..28dac13d 100644 --- a/bucket/ddc_bucket/account/messages.rs +++ b/bucket/ddc_bucket/account/messages.rs @@ -1,14 +1,13 @@ //! The public interface of Accounts and deposits. -use ink_prelude::vec::Vec; use ink_lang::codegen::{EmitEvent, StaticEnv}; +use ink_prelude::vec::Vec; -use crate::ddc_bucket::{AccountId, Balance, Cash, DdcBucket, Deposit, Payable, Result, TOKEN}; -use crate::ddc_bucket::Error::InsufficientBalance; use crate::ddc_bucket::perm::entity::Permission; +use crate::ddc_bucket::Error::InsufficientBalance; +use crate::ddc_bucket::{AccountId, Balance, Cash, DdcBucket, Deposit, Payable, Result, TOKEN}; impl DdcBucket { - // todo: remove this method as we can not support iterable data structures of arbitrary data size pub fn message_get_accounts(&self) -> Vec { self.accounts.accounts_keys.iter().cloned().collect() @@ -22,7 +21,10 @@ impl DdcBucket { // Create the account, if necessary. self.accounts.create_if_not_exist(account_id)?; - Self::env().emit_event(Deposit { account_id, value: cash.peek() }); + Self::env().emit_event(Deposit { + account_id, + value: cash.peek(), + }); let mut account = self.accounts.get(&account_id)?; account.deposit(cash); @@ -82,7 +84,9 @@ impl DdcBucket { } pub fn send_cash(destination: AccountId, cash: Cash) -> Result<()> { - if cash.peek() == 0 { return Ok(()); } + if cash.peek() == 0 { + return Ok(()); + } match Self::env().transfer(destination, cash.consume()) { Err(_e) => panic!("Transfer failed"), // Err(Error::TransferFailed), Ok(_v) => Ok(()), diff --git a/bucket/ddc_bucket/account/mod.rs b/bucket/ddc_bucket/account/mod.rs index e7bb8d95..300b6723 100644 --- a/bucket/ddc_bucket/account/mod.rs +++ b/bucket/ddc_bucket/account/mod.rs @@ -1,5 +1,5 @@ //! Account and deposit management. pub mod entity; +pub mod messages; pub mod store; -pub mod messages; \ No newline at end of file diff --git a/bucket/ddc_bucket/account/store.rs b/bucket/ddc_bucket/account/store.rs index edf98443..86f7f650 100644 --- a/bucket/ddc_bucket/account/store.rs +++ b/bucket/ddc_bucket/account/store.rs @@ -1,17 +1,14 @@ //! The store to create and access Accounts. -use ink_storage::Mapping; +use super::entity::Account; +use crate::ddc_bucket::flow::Flow; use crate::ddc_bucket::{ - AccountId, Balance, cash::Cash, Error::*, + cash::Cash, currency::CurrencyConverter, schedule::Schedule, AccountId, Balance, Error::*, Result, - schedule::Schedule, - currency::CurrencyConverter }; -use crate::ddc_bucket::flow::Flow; -use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_prelude::vec::Vec; -use super::entity::Account; - +use ink_storage::traits::{SpreadAllocate, SpreadLayout}; +use ink_storage::Mapping; // https://use.ink/datastructures/storage-layout#packed-vs-non-packed-layout // There is a buffer with only limited capacity (around 16KB in the default configuration) available. @@ -58,7 +55,12 @@ impl AccountStore { /// Increase the rate of the given flow starting from the given time. /// Lock the payment flow from the deposit of the payer account. - pub fn increase_flow(&mut self, start_ms: u64, extra_rate: Balance, flow: &mut Flow) -> Result<()> { + pub fn increase_flow( + &mut self, + start_ms: u64, + extra_rate: Balance, + flow: &mut Flow, + ) -> Result<()> { let extra_schedule = Schedule::new(start_ms, extra_rate); flow.schedule.add_schedule(extra_schedule.clone()); @@ -69,7 +71,12 @@ impl AccountStore { Ok(()) } - pub fn settle_flow(&mut self, now_ms: u64, flow: &mut Flow, curr_converter: &CurrencyConverter) -> Result { + pub fn settle_flow( + &mut self, + now_ms: u64, + flow: &mut Flow, + curr_converter: &CurrencyConverter, + ) -> Result { let flowed_usd = flow.schedule.take_value_at_time(now_ms); let flowed_cere = curr_converter.to_cere(flowed_usd); let (payable, cash) = Cash::borrow_payable_cash(flowed_cere); @@ -81,7 +88,11 @@ impl AccountStore { Ok(cash) } - pub fn flow_covered_until(&self, flow: &Flow, curr_converter: &CurrencyConverter) -> Result { + pub fn flow_covered_until( + &self, + flow: &Flow, + curr_converter: &CurrencyConverter, + ) -> Result { let account = self.get(&flow.from)?; let deposit_cere = account.deposit.peek(); let deposit_usd = curr_converter.to_usd(deposit_cere); diff --git a/bucket/ddc_bucket/admin.rs b/bucket/ddc_bucket/admin.rs index 9d7636d0..9d765f66 100644 --- a/bucket/ddc_bucket/admin.rs +++ b/bucket/ddc_bucket/admin.rs @@ -1,15 +1,13 @@ //! The privileged interface for admin tasks. -use ink_lang::codegen::{EmitEvent, StaticEnv}; use crate::ddc_bucket::perm::entity::Permission; -use crate::ddc_bucket::{AccountId, Balance, Cash, Payable, DdcBucket, NodeKey, NetworkFeeConfig, - NodeOwnershipTransferred, CdnNodeOwnershipTransferred, PermissionGranted, PermissionRevoked, Result, - BasisPoints, - Error::* +use crate::ddc_bucket::{ + AccountId, Balance, BasisPoints, Cash, CdnNodeOwnershipTransferred, DdcBucket, Error::*, + NetworkFeeConfig, NodeKey, NodeOwnershipTransferred, Payable, PermissionGranted, + PermissionRevoked, Result, }; +use ink_lang::codegen::{EmitEvent, StaticEnv}; impl DdcBucket { - - pub fn message_admin_grant_permission( &mut self, grantee: AccountId, @@ -19,16 +17,15 @@ impl DdcBucket { .map_err(|_| OnlySuperAdmin)?; self.grant_permission(grantee, permission)?; - - Self::env().emit_event(PermissionGranted { + + Self::env().emit_event(PermissionGranted { account_id: grantee, - permission + permission, }); Ok(()) } - pub fn message_admin_revoke_permission( &mut self, grantee: AccountId, @@ -38,91 +35,93 @@ impl DdcBucket { .map_err(|_| OnlySuperAdmin)?; self.revoke_permission(grantee, permission)?; - - Self::env().emit_event(PermissionRevoked { + + Self::env().emit_event(PermissionRevoked { account_id: grantee, - permission + permission, }); Ok(()) } - pub fn message_admin_transfer_node_ownership( &mut self, - node_key: NodeKey, - new_owner: AccountId + node_key: NodeKey, + new_owner: AccountId, ) -> Result<()> { - let admin = self.only_with_permission(Permission::SuperAdmin) + let admin = self + .only_with_permission(Permission::SuperAdmin) .map_err(|_| OnlySuperAdmin)?; let mut node = self.nodes.get(node_key)?; // allow node ownership transfer only if the current owner is the admin - node.only_provider(admin).map_err(|_| NodeProviderIsNotSuperAdmin)?; + node.only_provider(admin) + .map_err(|_| NodeProviderIsNotSuperAdmin)?; node.provider_id = new_owner; self.nodes.update(node_key, &node)?; - Self::env().emit_event(NodeOwnershipTransferred { + Self::env().emit_event(NodeOwnershipTransferred { account_id: new_owner, - node_key + node_key, }); Ok(()) } - pub fn message_admin_transfer_cdn_node_ownership( &mut self, - cdn_node_key: NodeKey, - new_owner: AccountId + cdn_node_key: NodeKey, + new_owner: AccountId, ) -> Result<()> { - let admin = self.only_with_permission(Permission::SuperAdmin) + let admin = self + .only_with_permission(Permission::SuperAdmin) .map_err(|_| OnlySuperAdmin)?; let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; // allow node ownership transfer only if the current owner is the admin - cdn_node.only_provider(admin).map_err(|_| CdnNodeOwnerIsNotSuperAdmin)?; + cdn_node + .only_provider(admin) + .map_err(|_| CdnNodeOwnerIsNotSuperAdmin)?; cdn_node.provider_id = new_owner; self.cdn_nodes.update(cdn_node_key, &cdn_node)?; - Self::env().emit_event(CdnNodeOwnershipTransferred { + Self::env().emit_event(CdnNodeOwnershipTransferred { account_id: new_owner, - cdn_node_key + cdn_node_key, }); Ok(()) } - pub fn message_admin_withdraw(&mut self, amount: Balance) -> Result<()> { - let admin = self.only_with_permission(Permission::SuperAdmin) + let admin = self + .only_with_permission(Permission::SuperAdmin) .map_err(|_| OnlySuperAdmin)?; Self::send_cash(admin, Cash(amount)) } - pub fn message_admin_set_protocol_fee_bp(&mut self, protocol_fee_bp: BasisPoints) -> Result<()> { + pub fn message_admin_set_protocol_fee_bp( + &mut self, + protocol_fee_bp: BasisPoints, + ) -> Result<()> { self.only_with_permission(Permission::SuperAdmin)?; self.protocol.set_protocol_fee_bp(protocol_fee_bp); Ok(()) } - pub fn message_admin_set_network_fee_config(&mut self, config: NetworkFeeConfig) -> Result<()> { self.only_with_permission(Permission::SuperAdmin)?; self.protocol.set_network_fee_config(config); Ok(()) } - pub fn message_admin_withdraw_revenues(&mut self, amount: u128) -> Result<()> { self.only_with_permission(Permission::SuperAdmin)?; self.protocol.withdraw_revenues(Payable(amount))?; Self::send_cash(self.protocol.get_protocol_fee_dest(), Cash(amount))?; Ok(()) } - - } diff --git a/bucket/ddc_bucket/bucket/entity.rs b/bucket/ddc_bucket/bucket/entity.rs index 53bd923c..379123b9 100644 --- a/bucket/ddc_bucket/bucket/entity.rs +++ b/bucket/ddc_bucket/bucket/entity.rs @@ -1,17 +1,13 @@ //! The data structure of Buckets. -use ink_prelude::vec::Vec; -use ink_prelude::string::String; -use ink_storage::traits::{SpreadAllocate, PackedAllocate, PackedLayout, SpreadLayout}; -use scale::{Decode, Encode}; -use ink_primitives::Key; -use crate::ddc_bucket::{ - AccountId, ClusterId, - Error::*, Result, -}; use crate::ddc_bucket::flow::Flow; use crate::ddc_bucket::node::entity::Resource; - +use crate::ddc_bucket::{AccountId, ClusterId, Error::*, Result}; +use ink_prelude::string::String; +use ink_prelude::vec::Vec; +use ink_primitives::Key; +use ink_storage::traits::{PackedAllocate, PackedLayout, SpreadAllocate, SpreadLayout}; +use scale::{Decode, Encode}; pub type BucketId = u32; pub type BucketParams = String; @@ -24,8 +20,8 @@ pub struct Bucket { pub flow: Flow, pub resource_reserved: Resource, pub public_availability: bool, - pub resource_consumption_cap: Resource, - pub bucket_params: BucketParams + pub resource_consumption_cap: Resource, + pub bucket_params: BucketParams, } // https://use.ink/3.x/ink-vs-solidity#nested-mappings--custom--advanced-structures @@ -46,7 +42,7 @@ pub struct BucketInStatus { // TODO: find a fix, then return the entire Bucket structure. pub resource_reserved: Resource, pub public_availability: bool, - pub resource_consumption_cap: Resource, + pub resource_consumption_cap: Resource, } #[derive(Clone, PartialEq, Encode, Decode)] @@ -64,7 +60,11 @@ pub const BUCKET_PARAMS_MAX_LEN: usize = 100_000; impl Bucket { pub fn only_owner(&self, caller: AccountId) -> Result<()> { - if self.owner_id == caller { Ok(()) } else { Err(OnlyOwner) } + if self.owner_id == caller { + Ok(()) + } else { + Err(OnlyOwner) + } } pub fn put_resource(&mut self, amount: Resource) { @@ -90,7 +90,6 @@ impl Bucket { self.bucket_params = bucket_params; Ok(()) } - } impl From for BucketInStatus { diff --git a/bucket/ddc_bucket/bucket/messages.rs b/bucket/ddc_bucket/bucket/messages.rs index 55125a81..28108bd1 100644 --- a/bucket/ddc_bucket/bucket/messages.rs +++ b/bucket/ddc_bucket/bucket/messages.rs @@ -3,22 +3,37 @@ use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; -use crate::ddc_bucket::{AccountId, Balance, BucketAllocated, BucketCreated, BucketSettlePayment, BucketAvailabilityUpdated, BucketParamsSet, DdcBucket, Result, Error::*}; use crate::ddc_bucket::cluster::entity::{Cluster, ClusterId}; use crate::ddc_bucket::node::entity::Resource; +use crate::ddc_bucket::{ + AccountId, Balance, BucketAllocated, BucketAvailabilityUpdated, BucketCreated, BucketParamsSet, + BucketSettlePayment, DdcBucket, Error::*, Result, +}; use super::entity::{Bucket, BucketId, BucketParams, BucketStatus}; impl DdcBucket { - pub fn message_bucket_create(&mut self, bucket_params: BucketParams, cluster_id: ClusterId, owner_id: Option) -> Result { + pub fn message_bucket_create( + &mut self, + bucket_params: BucketParams, + cluster_id: ClusterId, + owner_id: Option, + ) -> Result { let owner_id = owner_id.unwrap_or(Self::env().caller()); self.accounts.create_if_not_exist(owner_id)?; let bucket_id = self.buckets.create(owner_id, cluster_id, bucket_params); - Self::env().emit_event(BucketCreated { bucket_id, owner_id }); + Self::env().emit_event(BucketCreated { + bucket_id, + owner_id, + }); Ok(bucket_id) } - pub fn message_bucket_change_owner(&mut self, bucket_id: BucketId, owner_id: AccountId) -> Result<()> { + pub fn message_bucket_change_owner( + &mut self, + bucket_id: BucketId, + owner_id: AccountId, + ) -> Result<()> { let caller = Self::env().caller(); let mut bucket = self.buckets.get(bucket_id)?; bucket.only_owner(caller)?; @@ -27,7 +42,11 @@ impl DdcBucket { Ok(()) } - pub fn message_bucket_alloc_into_cluster(&mut self, bucket_id: BucketId, resource: Resource) -> Result<()> { + pub fn message_bucket_alloc_into_cluster( + &mut self, + bucket_id: BucketId, + resource: Resource, + ) -> Result<()> { let mut bucket = self.buckets.get(bucket_id)?; let mut cluster = self.clusters.get(bucket.cluster_id)?; Self::only_owner_or_cluster_manager(&bucket, &cluster)?; @@ -48,48 +67,66 @@ impl DdcBucket { let extra_rate = cluster.total_rent * resource as Balance; let now_ms = Self::env().block_timestamp(); - self.accounts.increase_flow(now_ms, extra_rate, &mut bucket.flow)?; + self.accounts + .increase_flow(now_ms, extra_rate, &mut bucket.flow)?; self.buckets.update(bucket_id, &bucket)?; - Self::env().emit_event(BucketAllocated { bucket_id, cluster_id: bucket.cluster_id, resource }); + Self::env().emit_event(BucketAllocated { + bucket_id, + cluster_id: bucket.cluster_id, + resource, + }); Ok(()) } - pub fn message_bucket_settle_payment(&mut self, bucket_id: BucketId) -> Result<()> { let mut bucket = self.buckets.get(bucket_id)?; let now_ms = Self::env().block_timestamp(); - let cash = self.accounts.settle_flow(now_ms, &mut bucket.flow, &self.protocol.curr_converter)?; + let cash = + self.accounts + .settle_flow(now_ms, &mut bucket.flow, &self.protocol.curr_converter)?; let mut cluster = self.clusters.get(bucket.cluster_id)?; cluster.revenues.increase(cash); self.clusters.update(bucket.cluster_id, &cluster)?; self.buckets.update(bucket_id, &bucket)?; - Self::env().emit_event(BucketSettlePayment { bucket_id, cluster_id: bucket.cluster_id }); + Self::env().emit_event(BucketSettlePayment { + bucket_id, + cluster_id: bucket.cluster_id, + }); Ok(()) } - - pub fn message_bucket_change_params(&mut self, bucket_id: BucketId, bucket_params: BucketParams) -> Result<()> { + pub fn message_bucket_change_params( + &mut self, + bucket_id: BucketId, + bucket_params: BucketParams, + ) -> Result<()> { let caller = Self::env().caller(); let mut bucket = self.buckets.get(bucket_id)?; bucket.only_owner(caller)?; bucket.set_params(bucket_params.clone())?; self.buckets.update(bucket_id, &bucket)?; - Self::env().emit_event(BucketParamsSet { bucket_id, bucket_params }); + Self::env().emit_event(BucketParamsSet { + bucket_id, + bucket_params, + }); Ok(()) } - pub fn message_bucket_get(&self, bucket_id: BucketId) -> Result { let bucket = self.buckets.get(bucket_id)?; self.bucket_calculate_status(bucket_id, bucket) } - - pub fn message_bucket_list(&self, offset: u32, limit: u32, filter_owner_id: Option) -> (Vec, u32) { + pub fn message_bucket_list( + &self, + offset: u32, + limit: u32, + filter_owner_id: Option, + ) -> (Vec, u32) { let mut bucket_statuses = Vec::with_capacity(limit as usize); for bucket_id in offset..offset + limit { let bucket = match self.buckets.buckets.get(bucket_id) { @@ -105,16 +142,14 @@ impl DdcBucket { // Collect all the details of the bucket. match self.bucket_calculate_status(bucket_id, bucket.clone()) { Err(_) => continue, // Skip on unexpected error. - Ok(status) => - bucket_statuses.push(status), + Ok(status) => bucket_statuses.push(status), }; } (bucket_statuses, self.buckets.next_bucket_id) } - pub fn message_bucket_list_for_account(&self, owner_id: AccountId) -> Vec { - let mut result : Vec = Vec::new(); + let mut result: Vec = Vec::new(); for bucket_id in 0..self.buckets.next_bucket_id { let bucket = self.buckets.get(bucket_id).unwrap(); @@ -127,18 +162,34 @@ impl DdcBucket { result } - - pub fn bucket_calculate_status(&self, bucket_id: BucketId, bucket: Bucket) -> Result { + pub fn bucket_calculate_status( + &self, + bucket_id: BucketId, + bucket: Bucket, + ) -> Result { let mut writer_ids = self.buckets.get_bucket_readers(bucket_id); writer_ids.push(bucket.owner_id); - let rent_covered_until_ms = self.accounts.flow_covered_until(&bucket.flow, &self.protocol.curr_converter)?; + let rent_covered_until_ms = self + .accounts + .flow_covered_until(&bucket.flow, &self.protocol.curr_converter)?; let reader_ids = self.buckets.get_bucket_readers(bucket_id); let bucket_params = bucket.bucket_params.clone(); - Ok(BucketStatus { bucket_id, params: bucket_params, bucket: bucket.into(), writer_ids, reader_ids, rent_covered_until_ms }) + Ok(BucketStatus { + bucket_id, + params: bucket_params, + bucket: bucket.into(), + writer_ids, + reader_ids, + rent_covered_until_ms, + }) } - pub fn message_bucket_set_resource_cap(&mut self, bucket_id: BucketId, new_resource_cap: Resource) -> Result<()> { + pub fn message_bucket_set_resource_cap( + &mut self, + bucket_id: BucketId, + new_resource_cap: Resource, + ) -> Result<()> { let mut bucket = self.buckets.get(bucket_id)?; let cluster = self.clusters.get(bucket.cluster_id)?; @@ -149,16 +200,23 @@ impl DdcBucket { Ok(()) } - pub fn message_bucket_set_availability(&mut self, bucket_id: BucketId, public_availability: bool) -> Result<()> { + pub fn message_bucket_set_availability( + &mut self, + bucket_id: BucketId, + public_availability: bool, + ) -> Result<()> { let mut bucket = self.buckets.get(bucket_id)?; let cluster = self.clusters.get(bucket.cluster_id)?; - + Self::only_owner_or_cluster_manager(&bucket, &cluster)?; bucket.set_availability(public_availability); self.buckets.update(bucket_id, &bucket)?; - Self::env().emit_event(BucketAvailabilityUpdated { bucket_id, public_availability }); + Self::env().emit_event(BucketAvailabilityUpdated { + bucket_id, + public_availability, + }); Ok(()) } @@ -166,22 +224,34 @@ impl DdcBucket { self.buckets.get_bucket_writers(bucket_id) } - pub fn message_grant_writer_permission(&mut self, bucket_id: BucketId, writer: AccountId) -> Result<()> { + pub fn message_grant_writer_permission( + &mut self, + bucket_id: BucketId, + writer: AccountId, + ) -> Result<()> { let bucket = self.buckets.get(bucket_id)?; let cluster = self.clusters.get(bucket.cluster_id)?; Self::only_owner_or_cluster_manager(&bucket, &cluster)?; - self.buckets.grant_writer_permission(bucket_id, writer).unwrap(); + self.buckets + .grant_writer_permission(bucket_id, writer) + .unwrap(); Ok(()) } - pub fn message_revoke_writer_permission(&mut self, bucket_id: BucketId, writer: AccountId) -> Result<()> { + pub fn message_revoke_writer_permission( + &mut self, + bucket_id: BucketId, + writer: AccountId, + ) -> Result<()> { let bucket = self.buckets.get(bucket_id)?; let cluster = self.clusters.get(bucket.cluster_id)?; Self::only_owner_or_cluster_manager(&bucket, &cluster)?; - self.buckets.revoke_writer_permission(bucket_id, writer).unwrap(); + self.buckets + .revoke_writer_permission(bucket_id, writer) + .unwrap(); Ok(()) } @@ -190,28 +260,42 @@ impl DdcBucket { self.buckets.get_bucket_readers(bucket_id) } - pub fn message_grant_reader_permission(&mut self, bucket_id: BucketId, reader: AccountId) -> Result<()> { + pub fn message_grant_reader_permission( + &mut self, + bucket_id: BucketId, + reader: AccountId, + ) -> Result<()> { let bucket = self.buckets.get(bucket_id)?; let cluster = self.clusters.get(bucket.cluster_id)?; Self::only_owner_or_cluster_manager(&bucket, &cluster)?; - self.buckets.grant_reader_permission(bucket_id, reader).unwrap(); + self.buckets + .grant_reader_permission(bucket_id, reader) + .unwrap(); Ok(()) } - pub fn message_revoke_reader_permission(&mut self, bucket_id: BucketId, reader: AccountId) -> Result<()> { + pub fn message_revoke_reader_permission( + &mut self, + bucket_id: BucketId, + reader: AccountId, + ) -> Result<()> { let bucket = self.buckets.get(bucket_id)?; let cluster = self.clusters.get(bucket.cluster_id)?; Self::only_owner_or_cluster_manager(&bucket, &cluster)?; - self.buckets.revoke_reader_permission(bucket_id, reader).unwrap(); + self.buckets + .revoke_reader_permission(bucket_id, reader) + .unwrap(); Ok(()) } fn only_owner_or_cluster_manager(bucket: &Bucket, cluster: &Cluster) -> Result<()> { let caller = Self::env().caller(); - cluster.only_manager(caller).or_else(|_| bucket.only_owner(caller)) + cluster + .only_manager(caller) + .or_else(|_| bucket.only_owner(caller)) } -} \ No newline at end of file +} diff --git a/bucket/ddc_bucket/bucket/mod.rs b/bucket/ddc_bucket/bucket/mod.rs index bf0ae353..cd2face0 100644 --- a/bucket/ddc_bucket/bucket/mod.rs +++ b/bucket/ddc_bucket/bucket/mod.rs @@ -1,5 +1,5 @@ //! Bucket management. pub mod entity; -pub mod store; pub mod messages; +pub mod store; diff --git a/bucket/ddc_bucket/bucket/store.rs b/bucket/ddc_bucket/bucket/store.rs index 6c44f032..c79fd2eb 100644 --- a/bucket/ddc_bucket/bucket/store.rs +++ b/bucket/ddc_bucket/bucket/store.rs @@ -1,13 +1,11 @@ -use ink_storage::traits::{SpreadAllocate, SpreadLayout}; -use ink_prelude::vec::Vec; -use ink_storage::Mapping; -use crate::ddc_bucket::{AccountId, Error::*, Result}; +use super::entity::{Bucket, BucketId, BucketParams}; use crate::ddc_bucket::cluster::entity::ClusterId; use crate::ddc_bucket::flow::Flow; use crate::ddc_bucket::schedule::Schedule; -use super::entity::{Bucket, BucketId, BucketParams}; - - +use crate::ddc_bucket::{AccountId, Error::*, Result}; +use ink_prelude::vec::Vec; +use ink_storage::traits::{SpreadAllocate, SpreadLayout}; +use ink_storage::Mapping; #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] @@ -15,23 +13,31 @@ pub struct BucketStore { pub next_bucket_id: u32, pub buckets: Mapping, pub writers: Mapping>, - pub readers: Mapping> + pub readers: Mapping>, } impl BucketStore { #[must_use] - pub fn create(&mut self, owner_id: AccountId, cluster_id: ClusterId, bucket_params: BucketParams) -> BucketId { + pub fn create( + &mut self, + owner_id: AccountId, + cluster_id: ClusterId, + bucket_params: BucketParams, + ) -> BucketId { let bucket_id = self.next_bucket_id; self.next_bucket_id = self.next_bucket_id + 1; let bucket = Bucket { owner_id, cluster_id, - flow: Flow { from: owner_id, schedule: Schedule::empty() }, + flow: Flow { + from: owner_id, + schedule: Schedule::empty(), + }, resource_reserved: 0, resource_consumption_cap: 0, public_availability: false, - bucket_params + bucket_params, }; self.buckets.insert(&bucket_id, &bucket); @@ -53,7 +59,9 @@ impl BucketStore { // get accounts with permission for bucket writing pub fn get_bucket_writers(&self, key: BucketId) -> Vec { - let writers : Vec = self.writers.get(&key) + let writers: Vec = self + .writers + .get(&key) .unwrap_or(Vec::new()) .iter() .cloned() @@ -88,7 +96,8 @@ impl BucketStore { // get accounts with permission for bucket reading pub fn get_bucket_readers(&self, key: BucketId) -> Vec { - self.readers.get(&key) + self.readers + .get(&key) .unwrap_or(Vec::new()) .iter() .cloned() @@ -120,5 +129,4 @@ impl BucketStore { Ok(()) } - } diff --git a/bucket/ddc_bucket/cash.rs b/bucket/ddc_bucket/cash.rs index d427c23f..191b6d16 100644 --- a/bucket/ddc_bucket/cash.rs +++ b/bucket/ddc_bucket/cash.rs @@ -2,20 +2,21 @@ //! //! These data structures facilitate the correctness of money-related calculations using the Rust type system. -use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout}; +use ink_storage::traits::{PackedLayout, SpreadAllocate, SpreadLayout}; use scale::{Decode, Encode}; -use crate::ddc_bucket::{Balance, Result}; use crate::ddc_bucket::Error::InsufficientBalance; +use crate::ddc_bucket::{Balance, Result}; // TODO: remove Clone. /// Cash represents some value that was taken from someone, and that must be credited to someone. #[must_use] -#[derive(Default, Clone, Copy, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] +#[derive( + Default, Clone, Copy, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout, +)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct Cash(pub Balance); - /// Payable represents some value that was credited to someone, and that must be paid by someone. /// Payable must be covered by Cash at all times to guarantee the balance of the contract. #[must_use] @@ -29,9 +30,13 @@ impl Cash { } #[must_use] - pub fn consume(self) -> Balance { self.0 } + pub fn consume(self) -> Balance { + self.0 + } - pub fn peek(&self) -> Balance { self.0 } + pub fn peek(&self) -> Balance { + self.0 + } pub fn increase(&mut self, cash: Cash) { self.0 += cash.consume(); @@ -57,9 +62,13 @@ impl Payable { } #[must_use] - pub fn consume(self) -> Balance { self.0 } + pub fn consume(self) -> Balance { + self.0 + } - pub fn peek(&self) -> Balance { self.0 } + pub fn peek(&self) -> Balance { + self.0 + } } // Implement TypeInfo with a field "value" to work with polkadot.js. @@ -75,7 +84,7 @@ impl ::scale_info::TypeInfo for Cash { .type_params([]) .composite( ::scale_info::build::Fields::named() - .field(|f| f.ty::().name("value").type_name("Balance")) + .field(|f| f.ty::().name("value").type_name("Balance")), ) } } diff --git a/bucket/ddc_bucket/cdn_node/entity.rs b/bucket/ddc_bucket/cdn_node/entity.rs index e6718ef2..e4b48c10 100644 --- a/bucket/ddc_bucket/cdn_node/entity.rs +++ b/bucket/ddc_bucket/cdn_node/entity.rs @@ -1,11 +1,10 @@ //! The data structure of Nodes. -use ink_storage::traits::{SpreadAllocate, PackedLayout, SpreadLayout, PackedAllocate}; -use scale::{Decode, Encode}; -use ink_primitives::Key; -use crate::ddc_bucket::{AccountId, Balance, ClusterId, NodeStatusInCluster, Error::*, Result}; +use crate::ddc_bucket::{AccountId, Balance, ClusterId, Error::*, NodeStatusInCluster, Result}; use ink_prelude::string::String; - +use ink_primitives::Key; +use ink_storage::traits::{PackedAllocate, PackedLayout, SpreadAllocate, SpreadLayout}; +use scale::{Decode, Encode}; pub type ProviderId = AccountId; pub type CdnNodeKey = AccountId; @@ -39,11 +38,10 @@ pub struct CdnNodeInfo { pub const CDN_NODE_PARAMS_MAX_LEN: usize = 100_000; impl CdnNode { - pub fn new( provider_id: AccountId, cdn_node_params: CdnNodeParams, - undistributed_payment: Balance + undistributed_payment: Balance, ) -> Result { let mut cdn_node = CdnNode { provider_id, @@ -52,7 +50,7 @@ impl CdnNode { cluster_id: None, status_in_cluster: None, }; - + cdn_node.set_params(cdn_node_params)?; Ok(cdn_node) } @@ -64,8 +62,9 @@ impl CdnNode { } pub fn only_without_cluster(&self) -> Result<()> { - self.cluster_id - .map_or(Ok(()), |cluster_id| Err(CdnNodeIsAddedToCluster(cluster_id))) + self.cluster_id.map_or(Ok(()), |cluster_id| { + Err(CdnNodeIsAddedToCluster(cluster_id)) + }) } pub fn only_with_cluster(&self, cluster_id: ClusterId) -> Result<()> { @@ -109,5 +108,4 @@ impl CdnNode { Err(InsufficientBalance) } } - -} \ No newline at end of file +} diff --git a/bucket/ddc_bucket/cdn_node/messages.rs b/bucket/ddc_bucket/cdn_node/messages.rs index 84de2e76..4112c452 100644 --- a/bucket/ddc_bucket/cdn_node/messages.rs +++ b/bucket/ddc_bucket/cdn_node/messages.rs @@ -1,26 +1,26 @@ //! The public interface to manage Nodes. +use crate::ddc_bucket::{ + AccountId, Balance, CdnNodeCreated, CdnNodeParamsSet, CdnNodeRemoved, DdcBucket, Result, +}; use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; -use crate::ddc_bucket::{AccountId, DdcBucket, CdnNodeCreated, CdnNodeRemoved, CdnNodeParamsSet, Result, Balance}; -use super::entity::{CdnNodeKey, CdnNodeInfo, CdnNodeParams}; +use super::entity::{CdnNodeInfo, CdnNodeKey, CdnNodeParams}; impl DdcBucket { - pub fn message_cdn_node_create( - &mut self, - cdn_node_key: CdnNodeKey, - cdn_node_params: CdnNodeParams + &mut self, + cdn_node_key: CdnNodeKey, + cdn_node_params: CdnNodeParams, ) -> Result { - let caller = Self::env().caller(); let undistributed_payment: Balance = 0; self.cdn_nodes.create( - cdn_node_key, - caller, - cdn_node_params.clone(), - undistributed_payment + cdn_node_key, + caller, + cdn_node_params.clone(), + undistributed_payment, )?; Self::env().emit_event(CdnNodeCreated { @@ -29,36 +29,27 @@ impl DdcBucket { cdn_node_params, undistributed_payment, }); - - Ok(cdn_node_key) + Ok(cdn_node_key) } - pub fn message_remove_cdn_node( - &mut self, - cdn_node_key: CdnNodeKey - ) -> Result<()> { - + pub fn message_remove_cdn_node(&mut self, cdn_node_key: CdnNodeKey) -> Result<()> { let caller = Self::env().caller(); let cdn_node = self.cdn_nodes.get(cdn_node_key)?; cdn_node.only_provider(caller)?; cdn_node.only_without_cluster()?; self.cdn_nodes.remove(cdn_node_key); - - Self::env().emit_event(CdnNodeRemoved { - cdn_node_key, - }); - Ok(()) + Self::env().emit_event(CdnNodeRemoved { cdn_node_key }); + Ok(()) } pub fn message_cdn_node_set_params( - &mut self, - cdn_node_key: CdnNodeKey, - cdn_node_params: CdnNodeParams + &mut self, + cdn_node_key: CdnNodeKey, + cdn_node_params: CdnNodeParams, ) -> Result<()> { - let caller = Self::env().caller(); let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; cdn_node.only_provider(caller)?; @@ -71,21 +62,22 @@ impl DdcBucket { }); Ok(()) - } pub fn message_cdn_node_get(&self, cdn_node_key: CdnNodeKey) -> Result { - let cdn_node = self.cdn_nodes.get(cdn_node_key)?; - Ok(CdnNodeInfo { - cdn_node_key, - cdn_node, + Ok(CdnNodeInfo { + cdn_node_key, + cdn_node, }) - } - pub fn message_cdn_node_list(&self, offset: u32, limit: u32, filter_provider_id: Option) -> (Vec, u32) { - + pub fn message_cdn_node_list( + &self, + offset: u32, + limit: u32, + filter_provider_id: Option, + ) -> (Vec, u32) { let mut cdn_nodes = Vec::with_capacity(limit as usize); for idx in offset..offset + limit { let cdn_node_key = match self.cdn_nodes.keys.get(idx as usize) { @@ -106,12 +98,10 @@ impl DdcBucket { cdn_node_key, cdn_node, }; - + cdn_nodes.push(status); } (cdn_nodes, self.cdn_nodes.keys.len().try_into().unwrap()) - } - } diff --git a/bucket/ddc_bucket/cdn_node/mod.rs b/bucket/ddc_bucket/cdn_node/mod.rs index 41a81e69..6c50e8f6 100644 --- a/bucket/ddc_bucket/cdn_node/mod.rs +++ b/bucket/ddc_bucket/cdn_node/mod.rs @@ -1,5 +1,5 @@ //! CDN Node management. pub mod entity; +pub mod messages; pub mod store; -pub mod messages; \ No newline at end of file diff --git a/bucket/ddc_bucket/cdn_node/store.rs b/bucket/ddc_bucket/cdn_node/store.rs index 898c3011..0fdde083 100644 --- a/bucket/ddc_bucket/cdn_node/store.rs +++ b/bucket/ddc_bucket/cdn_node/store.rs @@ -1,11 +1,10 @@ //! The store where to create and access Nodes. +use super::entity::{CdnNode, CdnNodeKey, CdnNodeParams}; +use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; +use ink_prelude::vec::Vec; use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_storage::Mapping; -use ink_prelude::vec::Vec; -use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; -use super::entity::{CdnNode, CdnNodeKey, CdnNodeParams}; - // https://use.ink/datastructures/storage-layout#packed-vs-non-packed-layout // There is a buffer with only limited capacity (around 16KB in the default configuration) available. @@ -14,20 +13,19 @@ pub const MAX_CDN_NODES_LEN_IN_VEC: usize = 400; #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct CdnNodeStore { - pub cdn_nodes: Mapping, - // todo: remove this vector as it can store an arbitrary number of elements and easily exceed 16KB limit - pub keys: Vec + pub cdn_nodes: Mapping, + // todo: remove this vector as it can store an arbitrary number of elements and easily exceed 16KB limit + pub keys: Vec, } impl CdnNodeStore { pub fn create( - &mut self, - cdn_node_key: CdnNodeKey, - provider_id: AccountId, - cdn_node_params: CdnNodeParams, - undistributed_payment: Balance, + &mut self, + cdn_node_key: CdnNodeKey, + provider_id: AccountId, + cdn_node_params: CdnNodeParams, + undistributed_payment: Balance, ) -> Result { - if self.cdn_nodes.contains(&cdn_node_key) { return Err(CdnNodeAlreadyExists); } @@ -36,35 +34,29 @@ impl CdnNodeStore { return Err(CdnNodesSizeExceedsLimit); } - let cdn_node = CdnNode::new( - provider_id, - cdn_node_params, - undistributed_payment - )?; + let cdn_node = CdnNode::new(provider_id, cdn_node_params, undistributed_payment)?; self.cdn_nodes.insert(&cdn_node_key, &cdn_node); self.keys.push(cdn_node_key); Ok(cdn_node_key) - } - pub fn get(&self, cdn_node_key: CdnNodeKey) -> Result { - self.cdn_nodes.get(cdn_node_key).ok_or(CdnNodeDoesNotExist) - } - - pub fn update(&mut self, cdn_node_key: CdnNodeKey, cdn_node: &CdnNode) -> Result<()> { - if !self.cdn_nodes.contains(&cdn_node_key) { - Err(CdnNodeDoesNotExist) - } else { - self.cdn_nodes.insert(cdn_node_key, cdn_node); - Ok(()) - } - } + pub fn get(&self, cdn_node_key: CdnNodeKey) -> Result { + self.cdn_nodes.get(cdn_node_key).ok_or(CdnNodeDoesNotExist) + } - pub fn remove(&mut self, cdn_node_key: CdnNodeKey) { - self.cdn_nodes.remove(cdn_node_key); - if let Some(pos) = self.keys.iter().position(|x| *x == cdn_node_key) { - self.keys.remove(pos); - }; - } + pub fn update(&mut self, cdn_node_key: CdnNodeKey, cdn_node: &CdnNode) -> Result<()> { + if !self.cdn_nodes.contains(&cdn_node_key) { + Err(CdnNodeDoesNotExist) + } else { + self.cdn_nodes.insert(cdn_node_key, cdn_node); + Ok(()) + } + } + pub fn remove(&mut self, cdn_node_key: CdnNodeKey) { + self.cdn_nodes.remove(cdn_node_key); + if let Some(pos) = self.keys.iter().position(|x| *x == cdn_node_key) { + self.keys.remove(pos); + }; + } } diff --git a/bucket/ddc_bucket/cluster/entity.rs b/bucket/ddc_bucket/cluster/entity.rs index d8c737f2..896dba5f 100644 --- a/bucket/ddc_bucket/cluster/entity.rs +++ b/bucket/ddc_bucket/cluster/entity.rs @@ -1,15 +1,14 @@ //! The data structure of Clusters. -use ink_prelude::vec::Vec; +use crate::ddc_bucket::cash::{Cash, Payable}; +use crate::ddc_bucket::cdn_node::entity::CdnNodeKey; +use crate::ddc_bucket::node::entity::{NodeKey, Resource}; +use crate::ddc_bucket::Error::{InsufficientBalance, OnlyClusterManager}; +use crate::ddc_bucket::{AccountId, Balance, Error::*, Result, VNodeToken}; use ink_prelude::string::String; -use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout, PackedAllocate}; -use scale::{Decode, Encode}; +use ink_prelude::vec::Vec; use ink_primitives::Key; -use crate::ddc_bucket::cash::{Cash, Payable}; -use crate::ddc_bucket::node::entity::{Resource, NodeKey}; -use crate::ddc_bucket::cdn_node::entity::{CdnNodeKey}; -use crate::ddc_bucket::Error::{OnlyClusterManager, InsufficientBalance}; -use crate::ddc_bucket::{AccountId, Balance, VNodeToken, Result, Error::*}; - +use ink_storage::traits::{PackedAllocate, PackedLayout, SpreadAllocate, SpreadLayout}; +use scale::{Decode, Encode}; pub type ClusterId = u32; pub type ClusterParams = String; @@ -19,7 +18,6 @@ pub type ClusterParams = String; pub const MAX_CLUSTER_NODES_LEN_IN_VEC: usize = 200; pub const MAX_CLUSTER_CDN_NODES_LEN_IN_VEC: usize = 200; - #[derive(Clone, PartialEq, Encode, Decode, SpreadAllocate, PackedLayout, SpreadLayout)] #[cfg_attr(feature = "std", derive(Debug, scale_info::TypeInfo))] pub struct Cluster { @@ -56,17 +54,15 @@ pub struct ClusterInfo { } pub const CLUSTER_PARAMS_MAX_LEN: usize = 100_000; -pub const CDN_USD_PER_GB : Balance = 104_857_600; +pub const CDN_USD_PER_GB: Balance = 104_857_600; pub const KB_PER_GB: Balance = 1_000_000; impl Cluster { - pub fn new( manager_id: AccountId, cluster_params: ClusterParams, resource_per_v_node: Resource, ) -> Result { - let mut cluster = Cluster { manager_id, cluster_params: ClusterParams::default(), @@ -79,7 +75,7 @@ impl Cluster { cdn_usd_per_gb: CDN_USD_PER_GB, // setting initially to 1 cent per GB cdn_revenues: Cash(0), }; - + cluster.set_params(cluster_params)?; Ok(cluster) } @@ -123,7 +119,7 @@ impl Cluster { pub fn remove_cdn_node(&mut self, cdn_node_key: CdnNodeKey) { if let Some(pos) = self.cdn_nodes_keys.iter().position(|x| *x == cdn_node_key) { self.cdn_nodes_keys.remove(pos); - } + } } pub fn set_params(&mut self, cluster_params: ClusterParams) -> Result<()> { @@ -137,11 +133,11 @@ impl Cluster { pub fn increase_rent(&mut self, amount: Balance) { self.total_rent += amount; } - + pub fn decrease_rent(&mut self, amount: Balance) { self.total_rent -= amount; } - + pub fn set_resource_per_v_node(&mut self, resource_per_v_node: Resource) { self.resource_per_v_node = resource_per_v_node; } @@ -173,5 +169,4 @@ impl Cluster { self.cdn_revenues.pay_unchecked(amount); Ok(()) } - } diff --git a/bucket/ddc_bucket/cluster/messages.rs b/bucket/ddc_bucket/cluster/messages.rs index 9e5b2ff4..11b6043d 100644 --- a/bucket/ddc_bucket/cluster/messages.rs +++ b/bucket/ddc_bucket/cluster/messages.rs @@ -2,28 +2,25 @@ use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; +use crate::ddc_bucket::bucket::entity::BucketId; use crate::ddc_bucket::cash::{Cash, Payable}; +use crate::ddc_bucket::cdn_node::entity::{CdnNode, CdnNodeKey}; use crate::ddc_bucket::cluster::entity::{ClusterInfo, KB_PER_GB}; -use crate::ddc_bucket::bucket::entity::{BucketId}; use crate::ddc_bucket::node::entity::{Node, NodeKey, Resource}; -use crate::ddc_bucket::cdn_node::entity::{CdnNode, CdnNodeKey}; -use crate::ddc_bucket::topology::store::{VNodeToken}; use crate::ddc_bucket::perm::entity::Permission; +use crate::ddc_bucket::topology::store::VNodeToken; use crate::ddc_bucket::ClusterNodeReplaced; use crate::ddc_bucket::{ - BASIS_POINTS, - AccountId, Balance, ClusterCreated, ClusterNodeAdded, ClusterNodeRemoved, - ClusterCdnNodeAdded, ClusterCdnNodeRemoved, ClusterDistributeRevenues, ClusterReserveResource, ClusterDistributeCdnRevenues, - ClusterRemoved, ClusterParamsSet, ClusterNodeStatusSet, ClusterCdnNodeStatusSet, PermissionGranted, PermissionRevoked, ClusterNodeReset, - DdcBucket, NodeStatusInCluster, Result, Error::* + AccountId, Balance, ClusterCdnNodeAdded, ClusterCdnNodeRemoved, ClusterCdnNodeStatusSet, + ClusterCreated, ClusterDistributeCdnRevenues, ClusterDistributeRevenues, ClusterNodeAdded, + ClusterNodeRemoved, ClusterNodeReset, ClusterNodeStatusSet, ClusterParamsSet, ClusterRemoved, + ClusterReserveResource, DdcBucket, Error::*, NodeStatusInCluster, PermissionGranted, + PermissionRevoked, Result, BASIS_POINTS, }; use super::entity::{ClusterId, ClusterParams}; - impl DdcBucket { - - pub fn message_cluster_create( &mut self, cluster_params: ClusterParams, @@ -31,12 +28,10 @@ impl DdcBucket { ) -> Result { let caller = Self::env().caller(); - let cluster_id = self.clusters.create( - caller, - cluster_params.clone(), - resource_per_v_node - )?; - + let cluster_id = + self.clusters + .create(caller, cluster_params.clone(), resource_per_v_node)?; + self.topology.create_topology(cluster_id)?; Self::env().emit_event(ClusterCreated { @@ -48,7 +43,6 @@ impl DdcBucket { Ok(cluster_id) } - pub fn message_cluster_add_node( &mut self, cluster_id: ClusterId, @@ -70,22 +64,22 @@ impl DdcBucket { node.reserve_resource(cluster.resource_per_v_node)?; cluster.increase_rent(node.rent_v_node_per_month); } - + self.nodes.update(node_key, &node)?; self.clusters.update(cluster_id, &cluster)?; - self.topology.add_node(cluster_id, node_key, v_nodes.clone())?; + self.topology + .add_node(cluster_id, node_key, v_nodes.clone())?; - Self::env().emit_event(ClusterNodeAdded { - cluster_id, + Self::env().emit_event(ClusterNodeAdded { + cluster_id, node_key, - v_nodes + v_nodes, }); Ok(()) } - pub fn message_cluster_remove_node( &mut self, cluster_id: ClusterId, @@ -96,12 +90,11 @@ impl DdcBucket { let mut node = self.nodes.get(node_key)?; let mut cluster = self.clusters.get(cluster_id)?; - if !cluster.only_manager(caller).is_ok() - && !node.only_provider(caller).is_ok() { - return Err(OnlyClusterManagerOrNodeProvider); + if !cluster.only_manager(caller).is_ok() && !node.only_provider(caller).is_ok() { + return Err(OnlyClusterManagerOrNodeProvider); } node.only_with_cluster(cluster_id)?; - + node.unset_cluster(); cluster.remove_node(node_key); let v_nodes = self.topology.get_v_nodes_by_node(node_key); @@ -109,21 +102,20 @@ impl DdcBucket { node.release_resource(cluster.resource_per_v_node); cluster.decrease_rent(node.rent_v_node_per_month); } - + self.nodes.update(node_key, &node)?; self.clusters.update(cluster_id, &cluster)?; self.topology.remove_node(cluster_id, node_key)?; - Self::env().emit_event(ClusterNodeRemoved { - cluster_id, - node_key + Self::env().emit_event(ClusterNodeRemoved { + cluster_id, + node_key, }); Ok(()) } - pub fn message_cluster_replace_node( &mut self, cluster_id: ClusterId, @@ -151,11 +143,8 @@ impl DdcBucket { self.nodes.update(new_node_key, &new_node)?; } - self.topology.replace_node( - cluster_id, - new_node_key, - v_nodes.clone() - )?; + self.topology + .replace_node(cluster_id, new_node_key, v_nodes.clone())?; Self::env().emit_event(ClusterNodeReplaced { cluster_id, @@ -166,7 +155,6 @@ impl DdcBucket { Ok(()) } - pub fn message_cluster_reset_node( &mut self, cluster_id: ClusterId, @@ -184,16 +172,12 @@ impl DdcBucket { let old_v_nodes = self.topology.get_v_nodes_by_node(node_key); if new_v_nodes.len() != old_v_nodes.len() { - if new_v_nodes.len() > old_v_nodes.len() { - for _i in 0..new_v_nodes.len() - old_v_nodes.len() { node.reserve_resource(cluster.resource_per_v_node)?; cluster.increase_rent(node.rent_v_node_per_month); } - } else if new_v_nodes.len() < old_v_nodes.len() { - for _i in 0..old_v_nodes.len() - new_v_nodes.len() { node.release_resource(cluster.resource_per_v_node); cluster.decrease_rent(node.rent_v_node_per_month); @@ -204,22 +188,18 @@ impl DdcBucket { self.clusters.update(cluster_id, &cluster)?; } - self.topology.reset_node( - cluster_id, - node_key, - new_v_nodes.clone() - )?; + self.topology + .reset_node(cluster_id, node_key, new_v_nodes.clone())?; Self::env().emit_event(ClusterNodeReset { cluster_id, node_key: node_key, - v_nodes: new_v_nodes + v_nodes: new_v_nodes, }); Ok(()) } - pub fn message_cluster_add_cdn_node( &mut self, cluster_id: ClusterId, @@ -240,15 +220,14 @@ impl DdcBucket { cluster.add_cdn_node(cdn_node_key)?; self.clusters.update(cluster_id, &cluster)?; - Self::env().emit_event(ClusterCdnNodeAdded { - cluster_id, - cdn_node_key + Self::env().emit_event(ClusterCdnNodeAdded { + cluster_id, + cdn_node_key, }); Ok(()) } - pub fn message_cluster_remove_cdn_node( &mut self, cluster_id: ClusterId, @@ -259,54 +238,46 @@ impl DdcBucket { let mut cdn_node: CdnNode = self.cdn_nodes.get(cdn_node_key)?; let mut cluster = self.clusters.get(cluster_id)?; - if !cluster.only_manager(caller).is_ok() - && !cdn_node.only_provider(caller).is_ok() { - return Err(OnlyClusterManagerOrCdnNodeProvider); + if !cluster.only_manager(caller).is_ok() && !cdn_node.only_provider(caller).is_ok() { + return Err(OnlyClusterManagerOrCdnNodeProvider); } cdn_node.only_with_cluster(cluster_id)?; - + cdn_node.unset_cluster(); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; cluster.remove_cdn_node(cdn_node_key); self.clusters.update(cluster_id, &cluster)?; - Self::env().emit_event(ClusterCdnNodeRemoved { - cluster_id, - cdn_node_key + Self::env().emit_event(ClusterCdnNodeRemoved { + cluster_id, + cdn_node_key, }); Ok(()) } - - pub fn message_cluster_remove( - &mut self, - cluster_id: ClusterId, - ) -> Result<()> { + pub fn message_cluster_remove(&mut self, cluster_id: ClusterId) -> Result<()> { let caller = Self::env().caller(); let cluster = self.clusters.get(cluster_id)?; cluster.only_manager(caller)?; cluster.only_without_nodes()?; - + self.clusters.remove(cluster_id); self.topology.remove_topology(cluster_id)?; - Self::env().emit_event(ClusterRemoved { - cluster_id, - }); + Self::env().emit_event(ClusterRemoved { cluster_id }); Ok(()) } - pub fn message_cluster_set_node_status( - &mut self, + &mut self, cluster_id: ClusterId, - node_key: NodeKey, - status_in_cluster: NodeStatusInCluster + node_key: NodeKey, + status_in_cluster: NodeStatusInCluster, ) -> Result<()> { let caller = Self::env().caller(); @@ -317,21 +288,20 @@ impl DdcBucket { node.change_status_in_cluster(status_in_cluster.clone()); self.nodes.update(node_key, &node)?; - Self::env().emit_event(ClusterNodeStatusSet { + Self::env().emit_event(ClusterNodeStatusSet { node_key, cluster_id, - status: status_in_cluster + status: status_in_cluster, }); - + Ok(()) } - pub fn message_cluster_set_cdn_node_status( - &mut self, + &mut self, cluster_id: ClusterId, - cdn_node_key: CdnNodeKey, - status_in_cluster: NodeStatusInCluster + cdn_node_key: CdnNodeKey, + status_in_cluster: NodeStatusInCluster, ) -> Result<()> { let caller = Self::env().caller(); @@ -342,50 +312,47 @@ impl DdcBucket { cdn_node.change_status_in_cluster(status_in_cluster.clone()); self.cdn_nodes.update(cdn_node_key, &cdn_node)?; - Self::env().emit_event(ClusterCdnNodeStatusSet { + Self::env().emit_event(ClusterCdnNodeStatusSet { cdn_node_key, cluster_id, - status: status_in_cluster + status: status_in_cluster, }); - + Ok(()) } - pub fn message_grant_trusted_manager_permission( &mut self, - manager_id: AccountId + manager_id: AccountId, ) -> Result<()> { let grantor = Self::env().caller(); let permission = Permission::ClusterManagerTrustedBy(grantor); self.grant_permission(manager_id, permission)?; - Self::env().emit_event(PermissionGranted { + Self::env().emit_event(PermissionGranted { account_id: manager_id, - permission + permission, }); - + Ok(()) } - pub fn message_revoke_trusted_manager_permission( &mut self, - manager_id: AccountId + manager_id: AccountId, ) -> Result<()> { let grantor = Self::env().caller(); let permission = Permission::ClusterManagerTrustedBy(grantor); self.revoke_permission(manager_id, permission)?; - Self::env().emit_event(PermissionRevoked { + Self::env().emit_event(PermissionRevoked { account_id: manager_id, - permission + permission, }); Ok(()) } - pub fn message_cluster_set_params( &mut self, cluster_id: ClusterId, @@ -397,15 +364,14 @@ impl DdcBucket { cluster.set_params(cluster_params.clone())?; self.clusters.update(cluster_id, &cluster)?; - Self::env().emit_event(ClusterParamsSet { + Self::env().emit_event(ClusterParamsSet { cluster_id, - cluster_params + cluster_params, }); Ok(()) } - pub fn message_cluster_set_resource_per_v_node( &mut self, cluster_id: ClusterId, @@ -416,7 +382,7 @@ impl DdcBucket { cluster.only_manager(caller)?; let old_resource_per_v_node = cluster.resource_per_v_node; - + cluster.set_resource_per_v_node(new_resource_per_v_node); let cluster_v_nodes = self.topology.get_v_nodes_by_cluster(cluster_id); let cluster_v_nodes_len: u32 = cluster_v_nodes.len().try_into().unwrap(); @@ -444,7 +410,6 @@ impl DdcBucket { Ok(()) } - pub fn message_cluster_get(&self, cluster_id: ClusterId) -> Result { let cluster = self.clusters.get(cluster_id)?; let cluster_v_nodes = self.topology.get_v_nodes_by_cluster(cluster_id); @@ -452,11 +417,10 @@ impl DdcBucket { Ok(ClusterInfo { cluster_id, cluster, - cluster_v_nodes + cluster_v_nodes, }) } - pub fn message_cluster_list( &self, offset: u32, @@ -482,7 +446,7 @@ impl DdcBucket { let cluster_info = ClusterInfo { cluster_id, cluster, - cluster_v_nodes + cluster_v_nodes, }; clusters.push(cluster_info); @@ -490,7 +454,6 @@ impl DdcBucket { (clusters, self.clusters.next_cluster_id) } - pub fn message_cluster_distribute_revenues(&mut self, cluster_id: ClusterId) -> Result<()> { let mut cluster = self.clusters.get(cluster_id)?; @@ -527,12 +490,11 @@ impl DdcBucket { Ok(()) } - // Set the price usd per gb pub fn message_cdn_set_rate( - &mut self, - cluster_id: ClusterId, - cdn_usd_per_gb: Balance + &mut self, + cluster_id: ClusterId, + cdn_usd_per_gb: Balance, ) -> Result<()> { let caller = Self::env().caller(); @@ -544,7 +506,6 @@ impl DdcBucket { Ok(()) } - // Get the price usd per gb pub fn message_cdn_get_rate(&self, cluster_id: ClusterId) -> Result { let cluster = self.clusters.get(cluster_id)?; @@ -552,15 +513,14 @@ impl DdcBucket { Ok(rate) } - // First payment is for aggregate consumption for account, second is the aggregate payment for the node (u32 for ids) pub fn message_cluster_put_cdn_revenue( - &mut self, - cluster_id: ClusterId, - aggregates_accounts: Vec<(AccountId, u128)>, - aggregates_nodes: Vec<(CdnNodeKey, u128)>, - aggregates_buckets: Vec<(BucketId, Resource)>, - era: u64 + &mut self, + cluster_id: ClusterId, + aggregates_accounts: Vec<(AccountId, u128)>, + aggregates_nodes: Vec<(CdnNodeKey, u128)>, + aggregates_buckets: Vec<(BucketId, Resource)>, + era: u64, ) -> Result<()> { self.only_validator()?; @@ -571,11 +531,15 @@ impl DdcBucket { let aggregate_payments_accounts; { let conv = &self.protocol.curr_converter; - aggregate_payments_accounts = aggregates_accounts.iter().map(|(client_id, resources_used)| { - let account_id = *client_id; - let cere_payment: Balance = conv.to_cere(*resources_used as Balance * cluster.cdn_usd_per_gb / KB_PER_GB ); - (account_id, cere_payment) - }).collect::>(); + aggregate_payments_accounts = aggregates_accounts + .iter() + .map(|(client_id, resources_used)| { + let account_id = *client_id; + let cere_payment: Balance = conv + .to_cere(*resources_used as Balance * cluster.cdn_usd_per_gb / KB_PER_GB); + (account_id, cere_payment) + }) + .collect::>(); } for &(client_id, payment) in aggregate_payments_accounts.iter() { @@ -584,9 +548,9 @@ impl DdcBucket { _undistributed_payment_accounts += payment; self.accounts.save(&client_id, &account); } else { - return Err(InsufficientBalance) + return Err(InsufficientBalance); } - }; + } let conv = self.protocol.curr_converter.clone(); let committer = &mut self.committer; @@ -595,13 +559,14 @@ impl DdcBucket { let mut cdn_node = self.cdn_nodes.get(cdn_node_key)?; let protocol_fee = self.protocol.get_protocol_fee_bp(); let protocol = &mut self.protocol; - - let payment = conv.to_cere(resources_used as Balance * cluster.cdn_usd_per_gb / KB_PER_GB ); + + let payment = + conv.to_cere(resources_used as Balance * cluster.cdn_usd_per_gb / KB_PER_GB); // let protocol_payment = payment * protocol_fee as u128/ BASIS_POINTS; let node_payment = payment * (BASIS_POINTS - protocol_fee) as u128 / BASIS_POINTS; let protocol_payment = payment - node_payment; - + cdn_node.put_payment(node_payment); protocol.put_revenues(Cash(protocol_payment)); @@ -629,7 +594,6 @@ impl DdcBucket { Ok(()) } - pub fn message_cluster_distribute_cdn_revenue(&mut self, cluster_id: ClusterId) -> Result<()> { let mut cluster = self.clusters.get(cluster_id)?; @@ -640,12 +604,12 @@ impl DdcBucket { self.capture_fee( self.protocol.get_cluster_management_fee_bp(), cluster.manager_id, - &mut cluster.cdn_revenues + &mut cluster.cdn_revenues, )?; // First accumulated revenues to distribute. let mut distributed_revenue = 0; - + for cdn_node_key in &cluster.cdn_nodes_keys { let cdn_node = self.cdn_nodes.get(*cdn_node_key)?; distributed_revenue += cdn_node.undistributed_payment; @@ -663,14 +627,12 @@ impl DdcBucket { self.cdn_nodes.update(*cdn_node_key, &cdn_node)?; Self::env().emit_event(ClusterDistributeCdnRevenues { - cluster_id, - provider_id: cdn_node.provider_id + cluster_id, + provider_id: cdn_node.provider_id, }); } self.clusters.update(cluster_id, &cluster)?; Ok(()) } - - } diff --git a/bucket/ddc_bucket/cluster/mod.rs b/bucket/ddc_bucket/cluster/mod.rs index 76c0f62f..26f0c149 100644 --- a/bucket/ddc_bucket/cluster/mod.rs +++ b/bucket/ddc_bucket/cluster/mod.rs @@ -1,5 +1,5 @@ //! Cluster management. pub mod entity; +pub mod messages; pub mod store; -pub mod messages; \ No newline at end of file diff --git a/bucket/ddc_bucket/cluster/store.rs b/bucket/ddc_bucket/cluster/store.rs index 0f1b970c..a79f5b54 100644 --- a/bucket/ddc_bucket/cluster/store.rs +++ b/bucket/ddc_bucket/cluster/store.rs @@ -1,10 +1,9 @@ //! The store where to create and access Clusters by ID. +use super::entity::{Cluster, ClusterId, ClusterParams}; +use crate::ddc_bucket::{AccountId, Error::*, Resource, Result}; use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_storage::Mapping; -use crate::ddc_bucket::{AccountId, Resource, Error::*, Result}; -use super::entity::{Cluster, ClusterId, ClusterParams}; - #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] @@ -23,11 +22,7 @@ impl ClusterStore { let cluster_id = self.next_cluster_id; self.next_cluster_id = self.next_cluster_id + 1; - let cluster = Cluster::new( - manager_id, - cluster_params, - resource_per_v_node - )?; + let cluster = Cluster::new(manager_id, cluster_params, resource_per_v_node)?; self.clusters.insert(&cluster_id, &cluster); Ok(cluster_id) @@ -49,5 +44,4 @@ impl ClusterStore { pub fn remove(&mut self, cluster_id: ClusterId) { self.clusters.remove(cluster_id); } - } diff --git a/bucket/ddc_bucket/committer/messages.rs b/bucket/ddc_bucket/committer/messages.rs index 35782dc4..8ffdd1c7 100644 --- a/bucket/ddc_bucket/committer/messages.rs +++ b/bucket/ddc_bucket/committer/messages.rs @@ -1,13 +1,16 @@ use ink_lang::codegen::StaticEnv; use ink_prelude::vec::Vec; -use crate::ddc_bucket::{AccountId, DdcBucket, CdnNodeKey, Result, Error::*}; -use super::store::{Commit, EraConfig, EraStatus, EraAndTimestamp}; - +use super::store::{Commit, EraAndTimestamp, EraConfig, EraStatus}; +use crate::ddc_bucket::{AccountId, CdnNodeKey, DdcBucket, Error::*, Result}; impl DdcBucket { - - pub fn message_set_commit(&mut self, cdn_owner: AccountId, cdn_node_key: CdnNodeKey, commit: Commit) -> Result<()> { + pub fn message_set_commit( + &mut self, + cdn_owner: AccountId, + cdn_node_key: CdnNodeKey, + commit: Commit, + ) -> Result<()> { self.committer.set_commit(cdn_owner, cdn_node_key, commit); Ok(()) } @@ -22,13 +25,13 @@ impl DdcBucket { pub fn message_set_era(&mut self, era_config: EraConfig) -> Result<()> { let caller = Self::env().caller(); - + match self.committer.set_era(caller, era_config) { - Err(_e) => Err(EraSettingFailed), + Err(_e) => Err(EraSettingFailed), Ok(_v) => Ok(()), } - } - + } + pub fn message_get_era(&self) -> EraStatus { let timestamp = Self::env().block_timestamp(); self.committer.get_era(timestamp) @@ -37,5 +40,4 @@ impl DdcBucket { pub fn message_get_era_settings(&self) -> EraConfig { self.committer.get_era_settings() } - -} \ No newline at end of file +} diff --git a/bucket/ddc_bucket/committer/mod.rs b/bucket/ddc_bucket/committer/mod.rs index 48079abd..0b51b05a 100644 --- a/bucket/ddc_bucket/committer/mod.rs +++ b/bucket/ddc_bucket/committer/mod.rs @@ -1,4 +1,4 @@ -// Committer Management +// Committer Management +pub mod messages; pub mod store; -pub mod messages; \ No newline at end of file diff --git a/bucket/ddc_bucket/committer/store.rs b/bucket/ddc_bucket/committer/store.rs index 6b2ded3b..f2a67672 100644 --- a/bucket/ddc_bucket/committer/store.rs +++ b/bucket/ddc_bucket/committer/store.rs @@ -1,14 +1,14 @@ -use crate::ddc_bucket::{AccountId, Hash, CdnNodeKey}; +use crate::ddc_bucket::{AccountId, CdnNodeKey, Hash}; -use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout}; use ink_prelude::vec::Vec; +use ink_storage::traits::{PackedLayout, SpreadAllocate, SpreadLayout}; use ink_storage::Mapping; #[derive(Debug, PartialEq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum Error { /// The caller is not the authorised operator of the smart contract - UnauthorizedOperator + UnauthorizedOperator, } /// Within the concept of era we would like to return specific phase to interested agents @@ -17,12 +17,12 @@ pub enum Error { pub enum Phase { Commit, Valiadation, - Payout + Payout, } #[derive(Debug, PartialEq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] -pub struct EraStatus { +pub struct EraStatus { current_era: u64, current_phase: Phase, previous_era: u64, @@ -30,23 +30,30 @@ pub struct EraStatus { prev_era_to_timestamp: u64, } -#[derive(Copy, Clone, SpreadAllocate, PackedLayout, SpreadLayout, scale::Encode, scale::Decode, Debug)] +#[derive( + Copy, Clone, SpreadAllocate, PackedLayout, SpreadLayout, scale::Encode, scale::Decode, Debug, +)] #[cfg_attr(feature = "std", derive(::scale_info::TypeInfo))] pub struct Commit { hash: Hash, total_logs: u128, from_timestamp: u64, to_timestamp: u64, -} +} -#[derive(Default, Copy, Clone, SpreadAllocate, SpreadLayout, scale::Encode, scale::Decode, Debug)] -#[cfg_attr(feature = "std", derive(::scale_info::TypeInfo, ink_storage::traits::StorageLayout))] +#[derive( + Default, Copy, Clone, SpreadAllocate, SpreadLayout, scale::Encode, scale::Decode, Debug, +)] +#[cfg_attr( + feature = "std", + derive(::scale_info::TypeInfo, ink_storage::traits::StorageLayout) +)] pub struct EraConfig { start: u64, interval: u64, commit_duration: u64, - validation_duration:u64 -} + validation_duration: u64, +} #[derive(Default, SpreadAllocate, SpreadLayout, Debug)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout))] @@ -54,7 +61,7 @@ pub struct CommitterStore { operator_id: AccountId, commits: Mapping>, validated_commits: Mapping, - era_settings: EraConfig + era_settings: EraConfig, } pub type Result = core::result::Result; @@ -75,7 +82,10 @@ impl CommitterStore { } let mut account_commits = self.commits.get(&cdn_owner).unwrap(); - let index = account_commits.iter().position(|(node, _)| *node == cdn_node_key).unwrap_or(usize::MAX); + let index = account_commits + .iter() + .position(|(node, _)| *node == cdn_node_key) + .unwrap_or(usize::MAX); if index != usize::MAX { account_commits.remove(index); } @@ -84,24 +94,35 @@ impl CommitterStore { } pub fn get_commit(&self, cdn_owner: AccountId) -> Vec<(CdnNodeKey, Commit)> { - self.commits.get(&cdn_owner).unwrap_or(Vec::<(CdnNodeKey, Commit)>::new()).iter().cloned().collect() + self.commits + .get(&cdn_owner) + .unwrap_or(Vec::<(CdnNodeKey, Commit)>::new()) + .iter() + .cloned() + .collect() } // Set the last validated commit per CDN node pub fn set_validated_commit(&mut self, cdn_node_key: CdnNodeKey, era: u64) -> Result<()> { - let prev_era_to_timestamp = self.era_settings.start + self.era_settings.interval * (era + 1); - self.validated_commits.insert(&cdn_node_key, &(era, prev_era_to_timestamp)); + let prev_era_to_timestamp = + self.era_settings.start + self.era_settings.interval * (era + 1); + self.validated_commits + .insert(&cdn_node_key, &(era, prev_era_to_timestamp)); Ok(()) } // Get the last era & timestamp validated per CDN node pub fn get_validate_commit(&self, cdn_node_key: CdnNodeKey) -> EraAndTimestamp { - self.validated_commits.get(&cdn_node_key).unwrap_or((0,0)) + self.validated_commits.get(&cdn_node_key).unwrap_or((0, 0)) } // Akin to modifier pub fn only_owner(&self, operator_id: AccountId) -> Result<()> { - if self.operator_id == operator_id { Ok(()) } else { Err(Error::UnauthorizedOperator) } + if self.operator_id == operator_id { + Ok(()) + } else { + Err(Error::UnauthorizedOperator) + } } // Set the new value for the era config @@ -116,10 +137,12 @@ impl CommitterStore { let era_start = self.era_settings.start; let interval = self.era_settings.interval; let elapsed_time_within_interval = (timestamp - era_start) % interval; - + let current_phase = if elapsed_time_within_interval < self.era_settings.commit_duration { Phase::Commit - } else if elapsed_time_within_interval < self.era_settings.validation_duration + self.era_settings.commit_duration { + } else if elapsed_time_within_interval + < self.era_settings.validation_duration + self.era_settings.commit_duration + { Phase::Valiadation } else { Phase::Payout @@ -130,12 +153,12 @@ impl CommitterStore { let prev_era_from_timestamp = era_start + interval * previous_era; let prev_era_to_timestamp = era_start + interval * current_era; - EraStatus { - current_era, - current_phase, - previous_era, - prev_era_from_timestamp, - prev_era_to_timestamp + EraStatus { + current_era, + current_phase, + previous_era, + prev_era_from_timestamp, + prev_era_to_timestamp, } } diff --git a/bucket/ddc_bucket/currency.rs b/bucket/ddc_bucket/currency.rs index 51731d76..6a3bcb66 100644 --- a/bucket/ddc_bucket/currency.rs +++ b/bucket/ddc_bucket/currency.rs @@ -1,8 +1,8 @@ //! The privileged interface for admin tasks. -use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout}; -use scale::{Decode, Encode}; use crate::ddc_bucket::{Balance, TOKEN}; +use ink_storage::traits::{PackedLayout, SpreadAllocate, SpreadLayout}; +use scale::{Decode, Encode}; pub const PRECISION: Balance = 10_000_000; @@ -10,18 +10,18 @@ pub type CERE = Balance; pub type USD = Balance; #[derive(Default, Clone, PartialEq, Encode, Decode, SpreadAllocate, PackedLayout, SpreadLayout)] -#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug, scale_info::TypeInfo))] -pub struct CurrencyConverter { +#[cfg_attr( + feature = "std", + derive(ink_storage::traits::StorageLayout, Debug, scale_info::TypeInfo) +)] +pub struct CurrencyConverter { /* how many USD for PRECISION CERE */ - rate: Balance + rate: Balance, } impl CurrencyConverter { - pub fn new() -> Self { - Self { - rate: PRECISION - } + Self { rate: PRECISION } } pub fn set_usd_per_cere(&mut self, usd_per_cere: USD) { diff --git a/bucket/ddc_bucket/flow.rs b/bucket/ddc_bucket/flow.rs index a847ed72..ba97501a 100644 --- a/bucket/ddc_bucket/flow.rs +++ b/bucket/ddc_bucket/flow.rs @@ -1,12 +1,9 @@ //! The Flow data structure represents an outgoing stream of payments from an account. -use ink_storage::traits::{SpreadAllocate, PackedLayout, SpreadLayout}; +use ink_storage::traits::{PackedLayout, SpreadAllocate, SpreadLayout}; use scale::{Decode, Encode}; -use crate::ddc_bucket::{ - AccountId, - schedule::Schedule, -}; +use crate::ddc_bucket::{schedule::Schedule, AccountId}; // TODO: remove Clone. #[derive(Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] diff --git a/bucket/ddc_bucket/node/entity.rs b/bucket/ddc_bucket/node/entity.rs index da10d002..975e8a0d 100644 --- a/bucket/ddc_bucket/node/entity.rs +++ b/bucket/ddc_bucket/node/entity.rs @@ -1,15 +1,15 @@ //! The data structure of Nodes. -use ink_storage::traits::{SpreadAllocate, PackedLayout, SpreadLayout, PackedAllocate}; -use ink_prelude::vec::Vec; use ink_prelude::string::String; +use ink_prelude::vec::Vec; +use ink_storage::traits::{PackedAllocate, PackedLayout, SpreadAllocate, SpreadLayout}; use scale::{Decode, Encode}; -use crate::ddc_bucket::{AccountId, Balance, VNodeToken, Error::*, Result}; use crate::ddc_bucket::cluster::entity::ClusterId; +use crate::ddc_bucket::{AccountId, Balance, Error::*, Result, VNodeToken}; -use ink_storage::traits::KeyPtr; use ink_primitives::Key; +use ink_storage::traits::KeyPtr; pub type ProviderId = AccountId; pub type NodeKey = AccountId; @@ -44,15 +44,15 @@ pub enum NodeStatusInCluster { OFFLINE, } -impl SpreadAllocate for NodeStatusInCluster { - fn allocate_spread(_: &mut KeyPtr) -> Self { - NodeStatusInCluster::ADDING +impl SpreadAllocate for NodeStatusInCluster { + fn allocate_spread(_: &mut KeyPtr) -> Self { + NodeStatusInCluster::ADDING } } impl Default for NodeStatusInCluster { fn default() -> Self { - NodeStatusInCluster::ADDING + NodeStatusInCluster::ADDING } } @@ -61,13 +61,12 @@ impl Default for NodeStatusInCluster { pub struct NodeInfo { pub node_key: NodeKey, pub node: Node, - pub v_nodes: Vec + pub v_nodes: Vec, } pub const NODE_PARAMS_MAX_LEN: usize = 100_000; impl Node { - pub fn new( provider_id: AccountId, node_params: NodeParams, @@ -126,7 +125,7 @@ impl Node { pub fn change_status_in_cluster(&mut self, status: NodeStatusInCluster) { self.status_in_cluster = Some(status); } - + pub fn release_resource(&mut self, amount: Resource) { self.free_resource += amount; } @@ -139,5 +138,4 @@ impl Node { Err(InsufficientNodeResources) } } - } diff --git a/bucket/ddc_bucket/node/messages.rs b/bucket/ddc_bucket/node/messages.rs index bb838c2e..9194733d 100644 --- a/bucket/ddc_bucket/node/messages.rs +++ b/bucket/ddc_bucket/node/messages.rs @@ -1,13 +1,13 @@ //! The public interface to manage Nodes. -use crate::ddc_bucket::node::entity::{NodeInfo, Resource, NodeKey, NodeParams}; -use crate::ddc_bucket::{AccountId, Balance, DdcBucket, NodeCreated, NodeRemoved, NodeParamsSet, Result}; +use crate::ddc_bucket::node::entity::{NodeInfo, NodeKey, NodeParams, Resource}; +use crate::ddc_bucket::{ + AccountId, Balance, DdcBucket, NodeCreated, NodeParamsSet, NodeRemoved, Result, +}; use ink_lang::codegen::{EmitEvent, StaticEnv}; use ink_prelude::vec::Vec; - impl DdcBucket { - pub fn message_node_create( &mut self, node_key: NodeKey, @@ -15,14 +15,13 @@ impl DdcBucket { capacity: Resource, rent_v_node_per_month: Balance, ) -> Result { - let caller = Self::env().caller(); self.nodes.create( - node_key, - caller, - node_params.clone(), + node_key, + caller, + node_params.clone(), capacity, - rent_v_node_per_month + rent_v_node_per_month, )?; Self::env().emit_event(NodeCreated { @@ -35,23 +34,16 @@ impl DdcBucket { Ok(node_key) } - pub fn message_node_remove( - &mut self, - node_key: NodeKey - ) -> Result<()> { - + pub fn message_node_remove(&mut self, node_key: NodeKey) -> Result<()> { let caller = Self::env().caller(); let node = self.nodes.get(node_key)?; node.only_provider(caller)?; node.only_without_cluster()?; self.nodes.remove(node_key); - Self::env().emit_event(NodeRemoved { - node_key, - }); + Self::env().emit_event(NodeRemoved { node_key }); Ok(()) - } pub fn message_node_set_params( @@ -59,7 +51,6 @@ impl DdcBucket { node_key: NodeKey, node_params: NodeParams, ) -> Result<()> { - let caller = Self::env().caller(); let mut node = self.nodes.get(node_key)?; node.only_provider(caller)?; @@ -72,7 +63,6 @@ impl DdcBucket { }); Ok(()) - } pub fn message_node_get(&self, node_key: NodeKey) -> Result { @@ -82,7 +72,7 @@ impl DdcBucket { Ok(NodeInfo { node_key, node, - v_nodes + v_nodes, }) } @@ -92,7 +82,6 @@ impl DdcBucket { limit: u32, filter_provider_id: Option, ) -> (Vec, u32) { - let mut nodes = Vec::with_capacity(limit as usize); for idx in offset..offset + limit { let node_key = match self.nodes.keys.get(idx as usize) { @@ -107,21 +96,19 @@ impl DdcBucket { continue; // Skip non-matches. } } - + let v_nodes = self.topology.get_v_nodes_by_node(node_key); // Include the complete status of matched items. let node_info = NodeInfo { node_key, node, - v_nodes + v_nodes, }; nodes.push(node_info); } (nodes, self.nodes.keys.len().try_into().unwrap()) - } - -} \ No newline at end of file +} diff --git a/bucket/ddc_bucket/node/mod.rs b/bucket/ddc_bucket/node/mod.rs index f9a8cdd9..07c7abbf 100644 --- a/bucket/ddc_bucket/node/mod.rs +++ b/bucket/ddc_bucket/node/mod.rs @@ -1,5 +1,5 @@ //! Node management. pub mod entity; +pub mod messages; pub mod store; -pub mod messages; \ No newline at end of file diff --git a/bucket/ddc_bucket/node/store.rs b/bucket/ddc_bucket/node/store.rs index 4f8c911b..7d7b0bee 100644 --- a/bucket/ddc_bucket/node/store.rs +++ b/bucket/ddc_bucket/node/store.rs @@ -1,10 +1,10 @@ //! The store where to create and access Nodes. -use ink_storage::traits::{SpreadAllocate, SpreadLayout}; +use super::entity::{Node, NodeKey, NodeParams, Resource}; +use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; use ink_prelude::vec::Vec; +use ink_storage::traits::{SpreadAllocate, SpreadLayout}; use ink_storage::Mapping; -use crate::ddc_bucket::{AccountId, Balance, Error::*, Result}; -use super::entity::{Node, NodeKey, NodeParams, Resource}; // https://use.ink/datastructures/storage-layout#packed-vs-non-packed-layout // There is a buffer with only limited capacity (around 16KB in the default configuration) available. @@ -15,7 +15,7 @@ pub const MAX_NODES_LEN_IN_VEC: usize = 400; pub struct NodeStore { pub nodes: Mapping, // todo: remove this vector as it can store an arbitrary number of elements and easily exceed 16KB limit - pub keys: Vec + pub keys: Vec, } impl NodeStore { @@ -27,21 +27,15 @@ impl NodeStore { capacity: Resource, rent_v_node_per_month: Balance, ) -> Result { - if self.nodes.contains(&node_key) { - return Err(NodeAlreadyExists); - } + return Err(NodeAlreadyExists); + } if self.keys.len() + 1 > MAX_NODES_LEN_IN_VEC { return Err(NodesSizeExceedsLimit); } - let node = Node::new( - provider_id, - node_params, - capacity, - rent_v_node_per_month - )?; + let node = Node::new(provider_id, node_params, capacity, rent_v_node_per_month)?; self.nodes.insert(node_key, &node); self.keys.push(node_key); @@ -67,5 +61,4 @@ impl NodeStore { self.keys.remove(pos); }; } - } diff --git a/bucket/ddc_bucket/perm/entity.rs b/bucket/ddc_bucket/perm/entity.rs index b5208fe6..3643e9ec 100644 --- a/bucket/ddc_bucket/perm/entity.rs +++ b/bucket/ddc_bucket/perm/entity.rs @@ -10,5 +10,5 @@ pub enum Permission { ClusterManagerTrustedBy(AccountId), SetExchangeRate, SuperAdmin, - Validator + Validator, } diff --git a/bucket/ddc_bucket/perm/messages.rs b/bucket/ddc_bucket/perm/messages.rs index 3d9c3b78..6ecb68a7 100644 --- a/bucket/ddc_bucket/perm/messages.rs +++ b/bucket/ddc_bucket/perm/messages.rs @@ -1,43 +1,52 @@ //! The public interface for permission management. -use ink_lang::codegen::{StaticEnv}; +use ink_lang::codegen::StaticEnv; -use crate::ddc_bucket::{AccountId, DdcBucket, Result, Error::* }; use crate::ddc_bucket::perm::entity::Permission; +use crate::ddc_bucket::{AccountId, DdcBucket, Error::*, Result}; impl DdcBucket { - - pub fn grant_permission(&mut self, account_id: AccountId, permission: Permission) -> Result<()> { + pub fn grant_permission( + &mut self, + account_id: AccountId, + permission: Permission, + ) -> Result<()> { self.perms.grant_permission(account_id, permission); Ok(()) } - pub fn revoke_permission(&mut self, account_id: AccountId, permission: Permission) -> Result<()> { + pub fn revoke_permission( + &mut self, + account_id: AccountId, + permission: Permission, + ) -> Result<()> { self.perms.revoke_permission(account_id, permission); Ok(()) } pub fn only_with_permission(&self, permission: Permission) -> Result { let caller = Self::env().caller(); - self.perms.has_permission(caller, permission) + self.perms + .has_permission(caller, permission) .then(|| caller) .ok_or(Unauthorized) } - pub fn only_trusted_cluster_manager(&self, provider_id: AccountId) -> Result { + pub fn only_trusted_cluster_manager(&self, provider_id: AccountId) -> Result { let caller = Self::env().caller(); let perm = Permission::ClusterManagerTrustedBy(provider_id); - self.perms.has_permission(caller, perm) + self.perms + .has_permission(caller, perm) .then(|| caller) .ok_or(OnlyTrustedClusterManager) } - pub fn only_validator(&self) -> Result { + pub fn only_validator(&self) -> Result { let caller = Self::env().caller(); let perm = Permission::Validator; - self.perms.has_permission(caller, perm) + self.perms + .has_permission(caller, perm) .then(|| caller) .ok_or(OnlyValidator) } - } diff --git a/bucket/ddc_bucket/perm/mod.rs b/bucket/ddc_bucket/perm/mod.rs index 88205564..169bb94d 100644 --- a/bucket/ddc_bucket/perm/mod.rs +++ b/bucket/ddc_bucket/perm/mod.rs @@ -1,5 +1,5 @@ //! Permission management. -pub mod store; +pub mod entity; pub mod messages; -pub mod entity; \ No newline at end of file +pub mod store; diff --git a/bucket/ddc_bucket/perm/store.rs b/bucket/ddc_bucket/perm/store.rs index deabc3fb..6c667a84 100644 --- a/bucket/ddc_bucket/perm/store.rs +++ b/bucket/ddc_bucket/perm/store.rs @@ -1,8 +1,8 @@ //! The store to create and access Accounts. use ink_prelude::vec::Vec; -use ink_storage::Mapping; use ink_storage::traits::{SpreadAllocate, SpreadLayout}; +use ink_storage::Mapping; use scale::Encode; use crate::ddc_bucket::AccountId; @@ -11,16 +11,14 @@ use super::entity::Permission; pub type TrustedBy = AccountId; - type PermKey = Vec; #[derive(SpreadAllocate, SpreadLayout, Default)] #[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug))] pub struct PermStore { - pub perms: Mapping + pub perms: Mapping, } - impl PermStore { pub fn grant_permission(&mut self, account_id: AccountId, permission: Permission) { let key = (account_id, permission).encode(); diff --git a/bucket/ddc_bucket/protocol/messages.rs b/bucket/ddc_bucket/protocol/messages.rs index 8a8d18d3..f0586164 100644 --- a/bucket/ddc_bucket/protocol/messages.rs +++ b/bucket/ddc_bucket/protocol/messages.rs @@ -1,10 +1,9 @@ //! The public interface to manage Protocol (fees included). -use crate::ddc_bucket::{DdcBucket, NetworkFeeConfig, BasisPoints}; use crate::ddc_bucket::cash::Cash; +use crate::ddc_bucket::{BasisPoints, DdcBucket, NetworkFeeConfig}; impl DdcBucket { - pub fn message_get_protocol_fee_bp(&self) -> BasisPoints { self.protocol.get_protocol_fee_bp() } @@ -12,9 +11,8 @@ impl DdcBucket { pub fn message_get_network_fee_config(&self) -> NetworkFeeConfig { self.protocol.get_network_fee_config() } - + pub fn message_get_protocol_revenues(&self) -> Cash { self.protocol.get_revenues() } - -} \ No newline at end of file +} diff --git a/bucket/ddc_bucket/protocol/mod.rs b/bucket/ddc_bucket/protocol/mod.rs index 15cd69c4..04516ccb 100644 --- a/bucket/ddc_bucket/protocol/mod.rs +++ b/bucket/ddc_bucket/protocol/mod.rs @@ -1,4 +1,4 @@ // Protocol Management (Fees, ...) +pub mod messages; pub mod store; -pub mod messages; \ No newline at end of file diff --git a/bucket/ddc_bucket/protocol/store.rs b/bucket/ddc_bucket/protocol/store.rs index 8683bcf9..2f72aa42 100644 --- a/bucket/ddc_bucket/protocol/store.rs +++ b/bucket/ddc_bucket/protocol/store.rs @@ -1,13 +1,17 @@ -use ink_storage::traits::{SpreadAllocate, SpreadLayout, PackedLayout}; -use scale::{Decode, Encode}; -use crate::ddc_bucket::{DdcBucket, AccountId, Error::*, Result, Balance, BasisPoints, BASIS_POINTS}; use crate::ddc_bucket::cash::{Cash, Payable}; use crate::ddc_bucket::currency::CurrencyConverter; - +use crate::ddc_bucket::{ + AccountId, Balance, BasisPoints, DdcBucket, Error::*, Result, BASIS_POINTS, +}; +use ink_storage::traits::{PackedLayout, SpreadAllocate, SpreadLayout}; +use scale::{Decode, Encode}; /// The configuration of fees. #[derive(Default, Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] -#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug, scale_info::TypeInfo))] +#[cfg_attr( + feature = "std", + derive(ink_storage::traits::StorageLayout, Debug, scale_info::TypeInfo) +)] pub struct NetworkFeeConfig { /// The fee rate from cluster revenues to the overall network. In basis points (1% of 1%). pub network_fee_bp: BasisPoints, @@ -18,24 +22,25 @@ pub struct NetworkFeeConfig { } impl NetworkFeeConfig { - pub fn new( network_fee_bp: BasisPoints, network_fee_destination: AccountId, - cluster_management_fee_bp: BasisPoints + cluster_management_fee_bp: BasisPoints, ) -> Self { Self { network_fee_bp, network_fee_destination, - cluster_management_fee_bp + cluster_management_fee_bp, } } - } #[derive(Default, Clone, PartialEq, Encode, Decode, SpreadAllocate, SpreadLayout, PackedLayout)] -#[cfg_attr(feature = "std", derive(ink_storage::traits::StorageLayout, Debug, scale_info::TypeInfo))] -pub struct ProtocolStore { +#[cfg_attr( + feature = "std", + derive(ink_storage::traits::StorageLayout, Debug, scale_info::TypeInfo) +)] +pub struct ProtocolStore { pub protocol_fee_bp: BasisPoints, pub protocol_fee_destination: AccountId, pub revenues: Cash, @@ -44,11 +49,10 @@ pub struct ProtocolStore { } impl ProtocolStore { - pub fn init( - &mut self, + &mut self, protocol_fee_bp: BasisPoints, - protocol_fee_dest: AccountId, + protocol_fee_dest: AccountId, network_fee_bp: BasisPoints, network_fee_dest: AccountId, cluster_fee_bp: BasisPoints, @@ -56,11 +60,8 @@ impl ProtocolStore { self.protocol_fee_bp = protocol_fee_bp; self.protocol_fee_destination = protocol_fee_dest; self.curr_converter = CurrencyConverter::new(); - self.network_fee_config = NetworkFeeConfig::new( - network_fee_bp, - network_fee_dest, - cluster_fee_bp - ); + self.network_fee_config = + NetworkFeeConfig::new(network_fee_bp, network_fee_dest, cluster_fee_bp); } pub fn get_protocol_fee_bp(&self) -> BasisPoints { @@ -110,25 +111,28 @@ impl ProtocolStore { pub fn get_cluster_management_fee_bp(&self) -> BasisPoints { self.network_fee_config.cluster_management_fee_bp } - } impl DdcBucket { /// Take a network fee from the given revenues (in place). pub fn capture_network_fee(&mut self, revenues: &mut Cash) -> Result<()> { self.capture_fee( - self.protocol.get_network_fee_bp(), - self.protocol.get_network_fee_dest(), - revenues + self.protocol.get_network_fee_bp(), + self.protocol.get_network_fee_dest(), + revenues, ) } /// Take a fee from the given revenues (in place) and send it to the destination. - pub fn capture_fee(&self, rate_bp: Balance, destination: AccountId, revenues: &mut Cash) -> Result<()> { + pub fn capture_fee( + &self, + rate_bp: Balance, + destination: AccountId, + revenues: &mut Cash, + ) -> Result<()> { let fee = revenues.peek() * rate_bp / BASIS_POINTS; let (payable, cash) = Cash::borrow_payable_cash(fee); revenues.pay(payable)?; Self::send_cash(destination, cash) } - -} \ No newline at end of file +} diff --git a/bucket/ddc_bucket/schedule.rs b/bucket/ddc_bucket/schedule.rs index d8e8c2b1..2c348983 100644 --- a/bucket/ddc_bucket/schedule.rs +++ b/bucket/ddc_bucket/schedule.rs @@ -1,6 +1,6 @@ //! The Schedule data structure implements a value that increases over time. -use ink_storage::traits::{SpreadAllocate, PackedLayout, SpreadLayout}; +use ink_storage::traits::{PackedLayout, SpreadAllocate, SpreadLayout}; use scale::{Decode, Encode}; use crate::ddc_bucket::Balance; @@ -19,7 +19,9 @@ impl Schedule { Schedule { rate, offset } } - pub fn empty() -> Schedule { Schedule::new(0, 0) } + pub fn empty() -> Schedule { + Schedule::new(0, 0) + } pub fn value_at_time(&self, time_ms: u64) -> Balance { let absolute = self.rate * time_ms as Balance / MS_PER_MONTH; @@ -28,7 +30,9 @@ impl Schedule { } pub fn time_of_value(&self, value: Balance) -> u64 { - if self.rate == 0 { return u64::MAX; } + if self.rate == 0 { + return u64::MAX; + } let absolute = self.offset + value; let time = absolute * MS_PER_MONTH / self.rate; @@ -52,4 +56,4 @@ impl Schedule { } } -pub const MS_PER_MONTH: u128 = 31 * 24 * 3600 * 1000; \ No newline at end of file +pub const MS_PER_MONTH: u128 = 31 * 24 * 3600 * 1000; diff --git a/bucket/ddc_bucket/tests/env_utils.rs b/bucket/ddc_bucket/tests/env_utils.rs index 9ca19645..b99a832b 100644 --- a/bucket/ddc_bucket/tests/env_utils.rs +++ b/bucket/ddc_bucket/tests/env_utils.rs @@ -1,14 +1,13 @@ #![allow(unused_variables, dead_code)] pub use ink_env::{ - call, test, block_timestamp, + block_timestamp, call, test, test::{advance_block, DefaultAccounts}, DefaultEnvironment, }; -use scale::Decode; use crate::ddc_bucket::*; - +use scale::Decode; pub type Event = ::Type; diff --git a/bucket/ddc_bucket/tests/mod.rs b/bucket/ddc_bucket/tests/mod.rs index de8381fd..6d068f21 100644 --- a/bucket/ddc_bucket/tests/mod.rs +++ b/bucket/ddc_bucket/tests/mod.rs @@ -1,10 +1,10 @@ mod env_utils; mod setup_utils; +mod test_account; mod test_admin; +mod test_bucket; +mod test_cdn_node; +mod test_cluster; mod test_currency; mod test_node; -mod test_cluster; -mod test_bucket; -mod test_account; -mod test_cdn_node; \ No newline at end of file diff --git a/bucket/ddc_bucket/tests/setup_utils.rs b/bucket/ddc_bucket/tests/setup_utils.rs index 4b362880..42efea88 100644 --- a/bucket/ddc_bucket/tests/setup_utils.rs +++ b/bucket/ddc_bucket/tests/setup_utils.rs @@ -1,6 +1,5 @@ - -use crate::ddc_bucket::*; use super::env_utils::*; +use crate::ddc_bucket::*; pub fn admin_id() -> AccountId { get_accounts().alice @@ -60,13 +59,28 @@ pub struct TestCluster { } pub fn setup_cluster() -> TestCluster { - let mut contract: DdcBucket = setup_contract(); - let provider_id0 = AccountId::from([0xae, 0x7d, 0xe8, 0x17, 0xa4, 0xa5, 0x12, 0x57, 0xd2, 0x49, 0x64, 0x28, 0x3b, 0x25, 0x69, 0x09, 0xdf, 0x0c, 0x99, 0x97, 0xc0, 0x3e, 0x2b, 0x88, 0x02, 0x02, 0xee, 0x10, 0xf4, 0x4d, 0x72, 0x48]); - let provider_id1 = AccountId::from([0xc4, 0xba, 0xfd, 0x6a, 0xa1, 0x5a, 0x14, 0xd6, 0xee, 0xf2, 0xea, 0x92, 0xb7, 0xc6, 0x84, 0x51, 0x68, 0x39, 0xbe, 0x96, 0xd6, 0xbf, 0xca, 0xa3, 0x68, 0xd2, 0x4f, 0xff, 0x09, 0x85, 0xa7, 0x1e]); - let provider_id2 = AccountId::from([0xfa, 0x01, 0x28, 0xf8, 0xe1, 0x32, 0xc6, 0x81, 0x21, 0x06, 0xa5, 0xce, 0xae, 0x6d, 0xcf, 0xf3, 0xd2, 0xc0, 0x1b, 0xb0, 0x13, 0xf2, 0xd7, 0x75, 0x6f, 0x20, 0xf9, 0x50, 0x00, 0xd6, 0xc7, 0x2b]); - let manager_id = AccountId::from([0xd2, 0xc5, 0xea, 0xa2, 0x0c, 0xd0, 0x4e, 0xfb, 0x3f, 0x10, 0xb8, 0xad, 0xa9, 0xa4, 0x4f, 0xe0, 0x85, 0x41, 0x1f, 0x59, 0xf2, 0x34, 0x1a, 0x92, 0xa3, 0x48, 0x4f, 0x04, 0x51, 0x87, 0x68, 0x54]); + let provider_id0 = AccountId::from([ + 0xae, 0x7d, 0xe8, 0x17, 0xa4, 0xa5, 0x12, 0x57, 0xd2, 0x49, 0x64, 0x28, 0x3b, 0x25, 0x69, + 0x09, 0xdf, 0x0c, 0x99, 0x97, 0xc0, 0x3e, 0x2b, 0x88, 0x02, 0x02, 0xee, 0x10, 0xf4, 0x4d, + 0x72, 0x48, + ]); + let provider_id1 = AccountId::from([ + 0xc4, 0xba, 0xfd, 0x6a, 0xa1, 0x5a, 0x14, 0xd6, 0xee, 0xf2, 0xea, 0x92, 0xb7, 0xc6, 0x84, + 0x51, 0x68, 0x39, 0xbe, 0x96, 0xd6, 0xbf, 0xca, 0xa3, 0x68, 0xd2, 0x4f, 0xff, 0x09, 0x85, + 0xa7, 0x1e, + ]); + let provider_id2 = AccountId::from([ + 0xfa, 0x01, 0x28, 0xf8, 0xe1, 0x32, 0xc6, 0x81, 0x21, 0x06, 0xa5, 0xce, 0xae, 0x6d, 0xcf, + 0xf3, 0xd2, 0xc0, 0x1b, 0xb0, 0x13, 0xf2, 0xd7, 0x75, 0x6f, 0x20, 0xf9, 0x50, 0x00, 0xd6, + 0xc7, 0x2b, + ]); + let manager_id = AccountId::from([ + 0xd2, 0xc5, 0xea, 0xa2, 0x0c, 0xd0, 0x4e, 0xfb, 0x3f, 0x10, 0xb8, 0xad, 0xa9, 0xa4, 0x4f, + 0xe0, 0x85, 0x41, 0x1f, 0x59, 0xf2, 0x34, 0x1a, 0x92, 0xa3, 0x48, 0x4f, 0x04, 0x51, 0x87, + 0x68, 0x54, + ]); set_balance(provider_id0, 1000 * TOKEN); set_balance(provider_id1, 1000 * TOKEN); @@ -82,13 +96,14 @@ pub fn setup_cluster() -> TestCluster { let node_capacity0 = 100; let rent_v_node_per_month0 = 10 * TOKEN; set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); - contract.node_create( - node_key0, - node_params0.clone(), - node_capacity0, - rent_v_node_per_month0, - ).unwrap(); - + contract + .node_create( + node_key0, + node_params0.clone(), + node_capacity0, + rent_v_node_per_month0, + ) + .unwrap(); // Create the 2nd storage node let node_key1 = AccountId::from([0x0b; 32]); @@ -96,13 +111,14 @@ pub fn setup_cluster() -> TestCluster { let node_capacity1 = 100; let rent_v_node_per_month1 = 10 * TOKEN; set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); - contract.node_create( - node_key1, - node_params1.clone(), - node_capacity1, - rent_v_node_per_month1 - ).unwrap(); - + contract + .node_create( + node_key1, + node_params1.clone(), + node_capacity1, + rent_v_node_per_month1, + ) + .unwrap(); // Create the 3rd storage node let node_key2 = AccountId::from([0x0c; 32]); @@ -110,127 +126,99 @@ pub fn setup_cluster() -> TestCluster { let node_capacity2 = 100; let rent_v_node_per_month2 = 10 * TOKEN; set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); - let node_key2 = contract.node_create( - node_key2, - node_params2.clone(), - node_capacity2, - rent_v_node_per_month2, - ).unwrap(); - + let node_key2 = contract + .node_create( + node_key2, + node_params2.clone(), + node_capacity2, + rent_v_node_per_month2, + ) + .unwrap(); // Create the 1st cdn node let cdn_node_key0 = AccountId::from([0x0d; 32]); let cdn_node_params0 = CdnNodeParams::from("{\"url\":\"https://ddc.cere.network/cdn/0\"}"); set_caller_value(provider_id0, CONTRACT_FEE_LIMIT); - contract.cdn_node_create( - cdn_node_key0, - cdn_node_params0.clone() - ).unwrap(); - + contract + .cdn_node_create(cdn_node_key0, cdn_node_params0.clone()) + .unwrap(); // Create the 2nd cdn node let cdn_node_key1 = AccountId::from([0x0e; 32]); let cdn_node_params1 = CdnNodeParams::from("{\"url\":\"https://ddc.cere.network/cdn/1\"}"); set_caller_value(provider_id1, CONTRACT_FEE_LIMIT); - contract.cdn_node_create( - cdn_node_key1, - cdn_node_params1.clone() - ).unwrap(); - + contract + .cdn_node_create(cdn_node_key1, cdn_node_params1.clone()) + .unwrap(); // Create the 3rd cdn node let cdn_node_key2 = AccountId::from([0x0f; 32]); let cdn_node_params2 = CdnNodeParams::from("{\"url\":\"https://ddc.cere.network/cdn/2\"}"); set_caller_value(provider_id2, CONTRACT_FEE_LIMIT); - contract.cdn_node_create( - cdn_node_key2, - cdn_node_params2.clone() - ).unwrap(); - + contract + .cdn_node_create(cdn_node_key2, cdn_node_params2.clone()) + .unwrap(); // Create a Cluster let cluster_params = ClusterParams::from("{}"); let resource_per_v_node = 10; set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - let cluster_id = contract.cluster_create( - cluster_params.clone(), - resource_per_v_node - ).unwrap(); - + let cluster_id = contract + .cluster_create(cluster_params.clone(), resource_per_v_node) + .unwrap(); // Grant trusted manager_id permission from node providers to the cluster manager_id for provider_id in [provider_id0, provider_id1, provider_id2] { set_caller_value(provider_id, CONTRACT_FEE_LIMIT); - contract.grant_trusted_manager_permission(manager_id).unwrap(); + contract + .grant_trusted_manager_permission(manager_id) + .unwrap(); let expected_perm = Permission::ClusterManagerTrustedBy(provider_id); assert!(contract.has_permission(manager_id, expected_perm)); } - // Add the 1st storage node to the Cluster let v_nodes0 = vec![1, 2, 3]; set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - contract.cluster_add_node( - cluster_id, - node_key0, - v_nodes0.clone() - ).unwrap(); - + contract + .cluster_add_node(cluster_id, node_key0, v_nodes0.clone()) + .unwrap(); // Add the 2nd storage node to the Cluster let v_nodes1 = vec![4, 5, 6]; set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - contract.cluster_add_node( - cluster_id, - node_key1, - v_nodes1.clone() - ).unwrap(); - + contract + .cluster_add_node(cluster_id, node_key1, v_nodes1.clone()) + .unwrap(); // Add the 3rd storage node to the Cluster let v_nodes2 = vec![7, 8, 9]; set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - contract.cluster_add_node( - cluster_id, - node_key2, - v_nodes2.clone() - ).unwrap(); - + contract + .cluster_add_node(cluster_id, node_key2, v_nodes2.clone()) + .unwrap(); // Add the 1st cdn node to the Cluster set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - contract.cluster_add_cdn_node( - cluster_id, - cdn_node_key0, - ).unwrap(); - + contract + .cluster_add_cdn_node(cluster_id, cdn_node_key0) + .unwrap(); // Add the 2nd cdn node to the Cluster set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - contract.cluster_add_cdn_node( - cluster_id, - cdn_node_key1, - ).unwrap(); - + contract + .cluster_add_cdn_node(cluster_id, cdn_node_key1) + .unwrap(); // Add the 3rd cdn node to the Cluster set_caller_value(manager_id, CONTRACT_FEE_LIMIT); - contract.cluster_add_cdn_node( - cluster_id, - cdn_node_key2, - ).unwrap(); + contract + .cluster_add_cdn_node(cluster_id, cdn_node_key2) + .unwrap(); - let nodes_keys = vec![ - node_key0, - node_key1, - node_key2 - ]; + let nodes_keys = vec![node_key0, node_key1, node_key2]; - let cdn_nodes_keys = vec![ - cdn_node_key0, - cdn_node_key1, - cdn_node_key2 - ]; + let cdn_nodes_keys = vec![cdn_node_key0, cdn_node_key1, cdn_node_key2]; let mut cluster_v_nodes = Vec::::new(); cluster_v_nodes.extend(v_nodes0.clone()); @@ -284,20 +272,25 @@ pub struct TestBucket { } pub fn setup_bucket(ctx: &mut TestCluster) -> TestBucket { - let owner_id = AccountId::from([0xd4, 0x8f, 0x63, 0x67, 0xe2, 0x15, 0x51, 0xdf, 0x11, 0x1c, 0x92, 0x69, 0x0d, 0x04, 0x3f, 0x75, 0xcb, 0x39, 0xf8, 0x27, 0xbb, 0xc7, 0x46, 0x4b, 0x8d, 0x5d, 0x70, 0xd1, 0x02, 0xaa, 0x71, 0x0a]); + let owner_id = AccountId::from([ + 0xd4, 0x8f, 0x63, 0x67, 0xe2, 0x15, 0x51, 0xdf, 0x11, 0x1c, 0x92, 0x69, 0x0d, 0x04, 0x3f, + 0x75, 0xcb, 0x39, 0xf8, 0x27, 0xbb, 0xc7, 0x46, 0x4b, 0x8d, 0x5d, 0x70, 0xd1, 0x02, 0xaa, + 0x71, 0x0a, + ]); set_balance(owner_id, 1000 * TOKEN); set_caller_value(owner_id, CONTRACT_FEE_LIMIT); - let bucket_id = ctx.contract.bucket_create( - "{}".to_string(), - ctx.cluster_id, - None - ).unwrap(); + let bucket_id = ctx + .contract + .bucket_create("{}".to_string(), ctx.cluster_id, None) + .unwrap(); // Reserve some resources for the bucket from the cluster. set_caller_value(owner_id, CONTRACT_FEE_LIMIT); let resource = 1; - ctx.contract.bucket_alloc_into_cluster(bucket_id, resource).unwrap(); + ctx.contract + .bucket_alloc_into_cluster(bucket_id, resource) + .unwrap(); // Deposit some value to pay for buckets. set_caller_value(owner_id, 10 * TOKEN); @@ -308,4 +301,4 @@ pub fn setup_bucket(ctx: &mut TestCluster) -> TestBucket { owner_id, resource, } -} \ No newline at end of file +} diff --git a/bucket/ddc_bucket/tests/test_account.rs b/bucket/ddc_bucket/tests/test_account.rs index 51a70fd7..40cef68d 100644 --- a/bucket/ddc_bucket/tests/test_account.rs +++ b/bucket/ddc_bucket/tests/test_account.rs @@ -1,15 +1,18 @@ use ink_lang as ink; -use crate::ddc_bucket::*; -use crate::ddc_bucket::Error::*; use super::env_utils::*; use super::setup_utils::*; -use crate::ddc_bucket::schedule::{Schedule}; - +use crate::ddc_bucket::schedule::Schedule; +use crate::ddc_bucket::Error::*; +use crate::ddc_bucket::*; #[ink::test] fn account_deposit_ok() { - let account_id = AccountId::from([0x76, 0x95, 0x7c, 0xa6, 0xbe, 0xf5, 0xa3, 0x6d, 0x67, 0x0d, 0x3a, 0x84, 0xc6, 0x0a, 0xe2, 0xbb, 0xc9, 0x5e, 0xee, 0xde, 0x3a, 0x5f, 0x27, 0x0e, 0x26, 0xe3, 0x43, 0x4c, 0x46, 0xe2, 0x98, 0x10]); + let account_id = AccountId::from([ + 0x76, 0x95, 0x7c, 0xa6, 0xbe, 0xf5, 0xa3, 0x6d, 0x67, 0x0d, 0x3a, 0x84, 0xc6, 0x0a, 0xe2, + 0xbb, 0xc9, 0x5e, 0xee, 0xde, 0x3a, 0x5f, 0x27, 0x0e, 0x26, 0xe3, 0x43, 0x4c, 0x46, 0xe2, + 0x98, 0x10, + ]); set_balance(account_id, 1000 * TOKEN); let mut contract = setup_contract(); diff --git a/bucket/ddc_bucket/tests/test_admin.rs b/bucket/ddc_bucket/tests/test_admin.rs index 6b54be8f..d378caa9 100644 --- a/bucket/ddc_bucket/tests/test_admin.rs +++ b/bucket/ddc_bucket/tests/test_admin.rs @@ -1,10 +1,9 @@ use ink_lang as ink; -use crate::ddc_bucket::*; -use crate::ddc_bucket::Error::*; use super::env_utils::*; use super::setup_utils::*; - +use crate::ddc_bucket::Error::*; +use crate::ddc_bucket::*; fn not_admin_id() -> AccountId { get_accounts().bob @@ -23,12 +22,11 @@ fn admin_init_ok() { assert!(!contract.has_permission(not_admin_id(), Permission::SetExchangeRate)); } - #[ink::test] fn admin_withdraw_ok() { let mut contract = setup_contract(); assert_eq!(balance_of(contract_id()), 10); - + set_caller(admin_id()); contract.admin_withdraw(9).unwrap(); @@ -42,11 +40,10 @@ fn admin_withdraw_err_if_not_admin() { let mut contract = setup_contract(); set_caller(not_admin_id()); - + contract.admin_withdraw(9).unwrap(); // panic. } - #[ink::test] fn admin_grant_ok() { let mut contract = setup_contract(); @@ -70,7 +67,6 @@ fn admin_grant_ok() { contract.admin_withdraw(9).unwrap(); } - #[ink::test] fn admin_grant_err_if_not_admin() { let mut contract = setup_contract(); @@ -78,15 +74,11 @@ fn admin_grant_err_if_not_admin() { set_caller_value(not_admin_id(), CONTRACT_FEE_LIMIT); assert_eq!( - contract.admin_grant_permission( - get_accounts().charlie, - Permission::SuperAdmin - ), + contract.admin_grant_permission(get_accounts().charlie, Permission::SuperAdmin), Err(OnlySuperAdmin) ); } - #[ink::test] #[should_panic] fn admin_revoke_ok() { @@ -110,7 +102,6 @@ fn admin_revoke_ok() { contract.admin_withdraw(9)?; } - #[ink::test] fn admin_revoke_err_if_not_admin() { let mut contract = setup_contract(); @@ -118,21 +109,25 @@ fn admin_revoke_err_if_not_admin() { set_caller_value(not_admin_id(), CONTRACT_FEE_LIMIT); assert_eq!( - contract.admin_revoke_permission( - admin_id(), - Permission::SuperAdmin - ), + contract.admin_revoke_permission(admin_id(), Permission::SuperAdmin), Err(OnlySuperAdmin) ); } - #[ink::test] fn admin_transfer_node_ownership_err_if_not_admin() { let mut contract = setup_contract(); - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); - let not_admin_id = AccountId::from([0x00, 0xc9, 0x91, 0xf1, 0x63, 0x0f, 0xb4, 0x51, 0xf6, 0x6c, 0x9e, 0xa5, 0xc6, 0xdd, 0xf3, 0x33, 0xd8, 0x48, 0x75, 0xc6, 0x22, 0xf5, 0xd3, 0xde, 0x4a, 0x39, 0xe7, 0x71, 0x6f, 0x74,0xf0, 0x49]); + let new_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); + let not_admin_id = AccountId::from([ + 0x00, 0xc9, 0x91, 0xf1, 0x63, 0x0f, 0xb4, 0x51, 0xf6, 0x6c, 0x9e, 0xa5, 0xc6, 0xdd, 0xf3, + 0x33, 0xd8, 0x48, 0x75, 0xc6, 0x22, 0xf5, 0xd3, 0xde, 0x4a, 0x39, 0xe7, 0x71, 0x6f, 0x74, + 0xf0, 0x49, + ]); set_balance(not_admin_id, 1000 * TOKEN); set_caller_value(not_admin_id, CONTRACT_FEE_LIMIT); @@ -146,27 +141,35 @@ fn admin_transfer_node_ownership_err_if_not_admin() { let node_info = contract.node_get(new_node_key)?; assert_eq!(node_info.node.provider_id, not_admin_id); - let new_owner_id = AccountId::from([0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, 0x47, 0x16]); + let new_owner_id = AccountId::from([ + 0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, + 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, + 0x47, 0x16, + ]); set_balance(new_owner_id, 1000 * TOKEN); set_caller(not_admin_id); assert_eq!( - contract.admin_transfer_node_ownership( - new_node_key, - new_owner_id - ), + contract.admin_transfer_node_ownership(new_node_key, new_owner_id), Err(OnlySuperAdmin) ); } - #[ink::test] fn admin_transfer_node_ownership_err_if_provider_is_not_admin() { let mut contract = setup_contract(); - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); - let not_admin_id = AccountId::from([0x00, 0xc9, 0x91, 0xf1, 0x63, 0x0f, 0xb4, 0x51, 0xf6, 0x6c, 0x9e, 0xa5, 0xc6, 0xdd, 0xf3, 0x33, 0xd8, 0x48, 0x75, 0xc6, 0x22, 0xf5, 0xd3, 0xde, 0x4a, 0x39, 0xe7, 0x71, 0x6f, 0x74,0xf0, 0x49]); + let new_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); + let not_admin_id = AccountId::from([ + 0x00, 0xc9, 0x91, 0xf1, 0x63, 0x0f, 0xb4, 0x51, 0xf6, 0x6c, 0x9e, 0xa5, 0xc6, 0xdd, 0xf3, + 0x33, 0xd8, 0x48, 0x75, 0xc6, 0x22, 0xf5, 0xd3, 0xde, 0x4a, 0x39, 0xe7, 0x71, 0x6f, 0x74, + 0xf0, 0x49, + ]); set_balance(not_admin_id, 1000 * TOKEN); set_caller_value(not_admin_id, CONTRACT_FEE_LIMIT); @@ -180,26 +183,30 @@ fn admin_transfer_node_ownership_err_if_provider_is_not_admin() { let node_info = contract.node_get(new_node_key)?; assert_eq!(node_info.node.provider_id, not_admin_id); - let new_owner_id = AccountId::from([0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, 0x47, 0x16]); + let new_owner_id = AccountId::from([ + 0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, + 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, + 0x47, 0x16, + ]); set_balance(new_owner_id, 1000 * TOKEN); set_caller(admin_id()); assert_eq!( - contract.admin_transfer_node_ownership( - new_node_key, - new_owner_id - ), + contract.admin_transfer_node_ownership(new_node_key, new_owner_id), Err(NodeProviderIsNotSuperAdmin) ); } - #[ink::test] fn admin_transfer_node_ownership_ok() { let mut contract = setup_contract(); - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); contract.node_create( new_node_key, @@ -211,35 +218,43 @@ fn admin_transfer_node_ownership_ok() { let node_info1 = contract.node_get(new_node_key)?; assert_eq!(node_info1.node.provider_id, admin_id()); - let new_owner_id = AccountId::from([0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, 0x47, 0x16]); + let new_owner_id = AccountId::from([ + 0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, + 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, + 0x47, 0x16, + ]); set_balance(new_owner_id, 1000 * TOKEN); set_caller(admin_id()); - contract.admin_transfer_node_ownership( - new_node_key, - new_owner_id - )?; + contract.admin_transfer_node_ownership(new_node_key, new_owner_id)?; let node_info2 = contract.node_get(new_node_key)?; assert_eq!(node_info2.node.provider_id, new_owner_id); assert!( matches!(get_events().pop().unwrap(), Event::NodeOwnershipTransferred(ev) if ev == - NodeOwnershipTransferred { - account_id: new_owner_id, - node_key: new_node_key + NodeOwnershipTransferred { + account_id: new_owner_id, + node_key: new_node_key } ) ); } - #[ink::test] fn admin_transfer_cdn_node_ownership_err_if_not_admin() { let mut contract = setup_contract(); - let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); - let not_admin_id = AccountId::from([0x00, 0xc9, 0x91, 0xf1, 0x63, 0x0f, 0xb4, 0x51, 0xf6, 0x6c, 0x9e, 0xa5, 0xc6, 0xdd, 0xf3, 0x33, 0xd8, 0x48, 0x75, 0xc6, 0x22, 0xf5, 0xd3, 0xde, 0x4a, 0x39, 0xe7, 0x71, 0x6f, 0x74,0xf0, 0x49]); + let new_cdn_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); + let not_admin_id = AccountId::from([ + 0x00, 0xc9, 0x91, 0xf1, 0x63, 0x0f, 0xb4, 0x51, 0xf6, 0x6c, 0x9e, 0xa5, 0xc6, 0xdd, 0xf3, + 0x33, 0xd8, 0x48, 0x75, 0xc6, 0x22, 0xf5, 0xd3, 0xde, 0x4a, 0x39, 0xe7, 0x71, 0x6f, 0x74, + 0xf0, 0x49, + ]); set_balance(not_admin_id, 1000 * TOKEN); set_caller_value(not_admin_id, CONTRACT_FEE_LIMIT); @@ -251,28 +266,35 @@ fn admin_transfer_cdn_node_ownership_err_if_not_admin() { let cdn_node_info = contract.cdn_node_get(new_cdn_node_key)?; assert_eq!(cdn_node_info.cdn_node.provider_id, not_admin_id); - let new_owner_id = AccountId::from([0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, 0x47, 0x16]); + let new_owner_id = AccountId::from([ + 0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, + 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, + 0x47, 0x16, + ]); set_balance(new_owner_id, 1000 * TOKEN); set_caller(not_admin_id); assert_eq!( - contract.admin_transfer_cdn_node_ownership( - new_cdn_node_key, - new_owner_id - ), - + contract.admin_transfer_cdn_node_ownership(new_cdn_node_key, new_owner_id), Err(OnlySuperAdmin) ); } - #[ink::test] fn admin_transfer_cdn_node_ownership_err_if_provider_is_not_admin() { let mut contract = setup_contract(); - let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); - let not_admin_id = AccountId::from([0x00, 0xc9, 0x91, 0xf1, 0x63, 0x0f, 0xb4, 0x51, 0xf6, 0x6c, 0x9e, 0xa5, 0xc6, 0xdd, 0xf3, 0x33, 0xd8, 0x48, 0x75, 0xc6, 0x22, 0xf5, 0xd3, 0xde, 0x4a, 0x39, 0xe7, 0x71, 0x6f, 0x74,0xf0, 0x49]); + let new_cdn_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); + let not_admin_id = AccountId::from([ + 0x00, 0xc9, 0x91, 0xf1, 0x63, 0x0f, 0xb4, 0x51, 0xf6, 0x6c, 0x9e, 0xa5, 0xc6, 0xdd, 0xf3, + 0x33, 0xd8, 0x48, 0x75, 0xc6, 0x22, 0xf5, 0xd3, 0xde, 0x4a, 0x39, 0xe7, 0x71, 0x6f, 0x74, + 0xf0, 0x49, + ]); set_balance(not_admin_id, 1000 * TOKEN); set_caller_value(not_admin_id, CONTRACT_FEE_LIMIT); @@ -284,26 +306,30 @@ fn admin_transfer_cdn_node_ownership_err_if_provider_is_not_admin() { let cdn_node_info = contract.cdn_node_get(new_cdn_node_key)?; assert_eq!(cdn_node_info.cdn_node.provider_id, not_admin_id); - let new_owner_id = AccountId::from([0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, 0x47, 0x16]); + let new_owner_id = AccountId::from([ + 0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, + 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, + 0x47, 0x16, + ]); set_balance(new_owner_id, 1000 * TOKEN); set_caller(admin_id()); assert_eq!( - contract.admin_transfer_cdn_node_ownership( - new_cdn_node_key, - new_owner_id - ), + contract.admin_transfer_cdn_node_ownership(new_cdn_node_key, new_owner_id), Err(CdnNodeOwnerIsNotSuperAdmin) ); } - #[ink::test] fn admin_transfer_cdn_node_ownership_ok() { let mut contract = setup_contract(); - let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_cdn_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); contract.cdn_node_create( new_cdn_node_key, @@ -313,23 +339,24 @@ fn admin_transfer_cdn_node_ownership_ok() { let cdn_node_info1 = contract.cdn_node_get(new_cdn_node_key)?; assert_eq!(cdn_node_info1.cdn_node.provider_id, admin_id()); - let new_owner_id = AccountId::from([0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, 0x47, 0x16]); + let new_owner_id = AccountId::from([ + 0xf8, 0x9e, 0xfb, 0x5c, 0x80, 0x72, 0x8e, 0x2a, 0x69, 0x54, 0x73, 0x32, 0x52, 0x8b, 0x03, + 0xb7, 0x9d, 0x2c, 0xd5, 0x06, 0xed, 0x38, 0x72, 0x95, 0x19, 0x9c, 0x6b, 0x8f, 0x7e, 0xa3, + 0x47, 0x16, + ]); set_balance(new_owner_id, 1000 * TOKEN); set_caller(admin_id()); - contract.admin_transfer_cdn_node_ownership( - new_cdn_node_key, - new_owner_id - )?; + contract.admin_transfer_cdn_node_ownership(new_cdn_node_key, new_owner_id)?; let cdn_node_info2 = contract.cdn_node_get(new_cdn_node_key)?; assert_eq!(cdn_node_info2.cdn_node.provider_id, new_owner_id); assert!( matches!(get_events().pop().unwrap(), Event::CdnNodeOwnershipTransferred(ev) if ev == - CdnNodeOwnershipTransferred { - account_id: new_owner_id, - cdn_node_key: new_cdn_node_key + CdnNodeOwnershipTransferred { + account_id: new_owner_id, + cdn_node_key: new_cdn_node_key } ) ); diff --git a/bucket/ddc_bucket/tests/test_bucket.rs b/bucket/ddc_bucket/tests/test_bucket.rs index 9f64e830..8524bbce 100644 --- a/bucket/ddc_bucket/tests/test_bucket.rs +++ b/bucket/ddc_bucket/tests/test_bucket.rs @@ -1,19 +1,17 @@ use ink_lang as ink; -use crate::ddc_bucket::*; -use crate::ddc_bucket::flow::Flow; -use crate::ddc_bucket::schedule::{Schedule, MS_PER_MONTH}; use super::env_utils::*; use super::setup_utils::*; - +use crate::ddc_bucket::flow::Flow; +use crate::ddc_bucket::schedule::{Schedule, MS_PER_MONTH}; +use crate::ddc_bucket::*; fn do_bucket_pays_cluster( ctx: &mut TestCluster, test_bucket: &TestBucket, usd_per_cere: Balance, ) -> Result<()> { - let expected_rent = - ctx.rent_v_node_per_month0 * ctx.v_nodes0.len() as Balance + let expected_rent = ctx.rent_v_node_per_month0 * ctx.v_nodes0.len() as Balance + ctx.rent_v_node_per_month1 * ctx.v_nodes1.len() as Balance + ctx.rent_v_node_per_month2 * ctx.v_nodes2.len() as Balance; @@ -43,9 +41,9 @@ fn do_bucket_pays_cluster( // Check the last event. let ev = get_events().pop().unwrap(); assert!(matches!(ev, Event::BucketSettlePayment(ev) if ev == - BucketSettlePayment { - bucket_id: test_bucket.bucket_id, - cluster_id: ctx.cluster_id + BucketSettlePayment { + bucket_id: test_bucket.bucket_id, + cluster_id: ctx.cluster_id } )); @@ -83,7 +81,6 @@ fn do_bucket_pays_cluster( Ok(()) } - #[ink::test] fn bucket_pays_cluster_ok() { let ctx = &mut setup_cluster(); @@ -91,7 +88,6 @@ fn bucket_pays_cluster_ok() { do_bucket_pays_cluster(ctx, test_bucket, 1).unwrap(); } - #[ink::test] fn bucket_pays_cluster_at_new_rate_ok() { let ctx = &mut setup_cluster(); @@ -100,26 +96,25 @@ fn bucket_pays_cluster_at_new_rate_ok() { // Set up an exchange rate manager_id. set_caller(admin_id()); ctx.contract - .admin_grant_permission(admin_id(), Permission::SetExchangeRate).unwrap(); - + .admin_grant_permission(admin_id(), Permission::SetExchangeRate) + .unwrap(); // Change the currency exchange rate. let usd_per_cere = 2; set_caller(admin_id()); - ctx.contract.account_set_usd_per_cere(usd_per_cere * TOKEN)?; + ctx.contract + .account_set_usd_per_cere(usd_per_cere * TOKEN)?; do_bucket_pays_cluster(ctx, test_bucket, usd_per_cere).unwrap(); } - #[ink::test] fn bucket_create_ok() { let ctx = &mut setup_cluster(); let test_bucket = &setup_bucket(ctx); // Check the structure of the bucket including the payment flow. - let total_rent = - ctx.rent_v_node_per_month0 * ctx.v_nodes0.len() as Balance + let total_rent = ctx.rent_v_node_per_month0 * ctx.v_nodes0.len() as Balance + ctx.rent_v_node_per_month1 * ctx.v_nodes1.len() as Balance + ctx.rent_v_node_per_month2 * ctx.v_nodes2.len() as Balance; @@ -134,7 +129,7 @@ fn bucket_create_ok() { resource_reserved: test_bucket.resource, public_availability: false, resource_consumption_cap: 0, - bucket_params: bucket_params + bucket_params: bucket_params, }; // Check the status of the bucket. @@ -174,7 +169,6 @@ fn bucket_create_ok() { assert_eq!(events.len(), 0, "all events must be checked"); } - #[ink::test] fn bucket_change_params_ok() { let ctx = &mut setup_cluster(); @@ -203,16 +197,27 @@ fn bucket_change_params_only_owner() { // Panic. } - #[ink::test] fn bucket_list_ok() { let mut ddc_bucket = setup_contract(); - let owner_id1 = AccountId::from([0xd8, 0x69, 0x19, 0x54, 0xea, 0xdc, 0x9a, 0xc0, 0x3d, 0x37, 0x56, 0x9f, 0x2a, 0xe8, 0xdf, 0x59, 0x34, 0x3f, 0x32, 0x65, 0xba, 0xd4, 0x16, 0xac, 0x07, 0xdf, 0x06, 0xeb, 0x4d, 0xbc, 0x6a, 0x66]); + let owner_id1 = AccountId::from([ + 0xd8, 0x69, 0x19, 0x54, 0xea, 0xdc, 0x9a, 0xc0, 0x3d, 0x37, 0x56, 0x9f, 0x2a, 0xe8, 0xdf, + 0x59, 0x34, 0x3f, 0x32, 0x65, 0xba, 0xd4, 0x16, 0xac, 0x07, 0xdf, 0x06, 0xeb, 0x4d, 0xbc, + 0x6a, 0x66, + ]); set_balance(owner_id1, 1000 * TOKEN); - let owner_id2 = AccountId::from([0x2a, 0x5f, 0xbc, 0xcf, 0x71, 0x0b, 0x65, 0x04, 0x88, 0x91, 0x12, 0x7e, 0x5e, 0xe3, 0x78, 0xdb, 0x48, 0x63, 0x09, 0x44, 0xcc, 0xc5, 0x75, 0xbd, 0xa5, 0xaa, 0xa5, 0x0e, 0x77, 0xab, 0x7b, 0x4e]); + let owner_id2 = AccountId::from([ + 0x2a, 0x5f, 0xbc, 0xcf, 0x71, 0x0b, 0x65, 0x04, 0x88, 0x91, 0x12, 0x7e, 0x5e, 0xe3, 0x78, + 0xdb, 0x48, 0x63, 0x09, 0x44, 0xcc, 0xc5, 0x75, 0xbd, 0xa5, 0xaa, 0xa5, 0x0e, 0x77, 0xab, + 0x7b, 0x4e, + ]); set_balance(owner_id2, 1000 * TOKEN); - let owner_id3 = AccountId::from([0x64, 0xef, 0xd7, 0xb4, 0x41, 0xb2, 0x58, 0xb5, 0x56, 0x6b, 0xfc, 0x4b, 0x19, 0xb8, 0xe5, 0x09, 0x5d, 0x17, 0xb3, 0xc3, 0x44, 0x38, 0x58, 0xa9, 0x7d, 0x20, 0x49, 0x39, 0xbd, 0xbd, 0xb6, 0x48]); + let owner_id3 = AccountId::from([ + 0x64, 0xef, 0xd7, 0xb4, 0x41, 0xb2, 0x58, 0xb5, 0x56, 0x6b, 0xfc, 0x4b, 0x19, 0xb8, 0xe5, + 0x09, 0x5d, 0x17, 0xb3, 0xc3, 0x44, 0x38, 0x58, 0xa9, 0x7d, 0x20, 0x49, 0x39, 0xbd, 0xbd, + 0xb6, 0x48, + ]); set_balance(owner_id3, 1000 * TOKEN); let cluster_id = 0; @@ -240,17 +245,11 @@ fn bucket_list_ok() { assert_eq!( ddc_bucket.bucket_list(0, 1, None), - ( - vec![bucket_status1.clone()], - count - ) + (vec![bucket_status1.clone()], count) ); assert_eq!( ddc_bucket.bucket_list(1, 1, None), - ( - vec![bucket_status2.clone()], - count - ) + (vec![bucket_status2.clone()], count) ); assert_eq!(ddc_bucket.bucket_list(count, 20, None), (vec![], count)); @@ -258,18 +257,12 @@ fn bucket_list_ok() { // Filter by owner. assert_eq!( ddc_bucket.bucket_list(0, 100, Some(owner_id1)), - ( - vec![bucket_status1.clone()], - count - ) + (vec![bucket_status1.clone()], count) ); assert_eq!( ddc_bucket.bucket_list(0, 100, Some(owner_id2)), - ( - vec![bucket_status2.clone()], - count - ) + (vec![bucket_status2.clone()], count) ); assert_eq!( diff --git a/bucket/ddc_bucket/tests/test_cdn_node.rs b/bucket/ddc_bucket/tests/test_cdn_node.rs index b37c47ef..57c51b30 100644 --- a/bucket/ddc_bucket/tests/test_cdn_node.rs +++ b/bucket/ddc_bucket/tests/test_cdn_node.rs @@ -2,49 +2,52 @@ use ink_lang as ink; use crate::ddc_bucket::Error::*; use crate::ddc_bucket::*; -use cdn_node::{entity::*}; +use cdn_node::entity::*; use super::env_utils::*; use super::setup_utils::*; - #[ink::test] fn cdn_node_create_err_if_node_exists() { let mut ctx = setup_cluster(); assert_eq!( - ctx.contract.cdn_node_create( - ctx.cdn_node_key1, - ctx.cdn_node_params1, - ), + ctx.contract + .cdn_node_create(ctx.cdn_node_key1, ctx.cdn_node_params1,), Err(CdnNodeAlreadyExists) ); } - #[ink::test] fn cdn_node_create_ok() { let mut ctx = setup_cluster(); - let new_provider_id = AccountId::from([0x76, 0x30, 0xc6, 0x96, 0x6f, 0xd3, 0x26, 0xba, 0x1a, 0xa0, 0x6f, 0xd8, 0x7f, 0x7b, 0xf2, 0xef, 0x14, 0x11, 0xf0, 0x0d, 0x00, 0xa9, 0xe7, 0x11, 0xdf, 0xd1, 0x65, 0x14, 0x5d, 0x01, 0xdb, 0x59]); + let new_provider_id = AccountId::from([ + 0x76, 0x30, 0xc6, 0x96, 0x6f, 0xd3, 0x26, 0xba, 0x1a, 0xa0, 0x6f, 0xd8, 0x7f, 0x7b, 0xf2, + 0xef, 0x14, 0x11, 0xf0, 0x0d, 0x00, 0xa9, 0xe7, 0x11, 0xdf, 0xd1, 0x65, 0x14, 0x5d, 0x01, + 0xdb, 0x59, + ]); set_balance(new_provider_id, 1000 * TOKEN); - let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); - let new_cdn_node_params = CdnNodeParams::from("{\"url\":\"https://ddc-1.cere.network/cdn/new\"}"); + let new_cdn_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); + let new_cdn_node_params = + CdnNodeParams::from("{\"url\":\"https://ddc-1.cere.network/cdn/new\"}"); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.cdn_node_create( - new_cdn_node_key, - new_cdn_node_params.clone() - )?; + ctx.contract + .cdn_node_create(new_cdn_node_key, new_cdn_node_params.clone())?; assert!( matches!(get_events().pop().unwrap(), Event::CdnNodeCreated(ev) if ev == - CdnNodeCreated { - cdn_node_key: new_cdn_node_key, - provider_id: new_provider_id, - undistributed_payment: 0, - cdn_node_params: new_cdn_node_params.clone() - }) + CdnNodeCreated { + cdn_node_key: new_cdn_node_key, + provider_id: new_provider_id, + undistributed_payment: 0, + cdn_node_params: new_cdn_node_params.clone() + }) ); let cdn_node_info = ctx.contract.cdn_node_get(new_cdn_node_key)?; @@ -56,15 +59,17 @@ fn cdn_node_create_ok() { status_in_cluster: None, }; assert!(matches!(cdn_node_info.cdn_node, _expected_cdn_node)); - } - #[ink::test] fn cdn_node_remove_err_if_not_provider() { let mut ctx = setup_cluster(); - let not_provider_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_provider_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); set_balance(not_provider_id, 1000 * TOKEN); set_caller(not_provider_id); @@ -74,7 +79,6 @@ fn cdn_node_remove_err_if_not_provider() { ); } - #[ink::test] fn cdn_node_remove_err_if_node_in_cluster() { let mut ctx = setup_cluster(); @@ -86,13 +90,13 @@ fn cdn_node_remove_err_if_node_in_cluster() { ); } - #[ink::test] fn cdn_node_remove_ok() { let mut ctx = setup_cluster(); set_caller(ctx.provider_id1); - ctx.contract.cluster_remove_cdn_node(ctx.cluster_id, ctx.cdn_node_key1)?; + ctx.contract + .cluster_remove_cdn_node(ctx.cluster_id, ctx.cdn_node_key1)?; ctx.contract.cdn_node_remove(ctx.cdn_node_key1)?; assert!( @@ -109,27 +113,27 @@ fn cdn_node_remove_ok() { ); } - #[ink::test] fn cdn_node_set_params_err_if_not_provider() { let mut ctx = setup_cluster(); - let not_provider = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_provider = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); set_balance(not_provider, 1000 * TOKEN); // Change params.not_provider let new_cdn_node_params = CdnNodeParams::from("new cdn node params"); set_caller_value(not_provider, CONTRACT_FEE_LIMIT); assert_eq!( - ctx.contract.cdn_node_set_params( - ctx.cdn_node_key0, - new_cdn_node_params - ), + ctx.contract + .cdn_node_set_params(ctx.cdn_node_key0, new_cdn_node_params), Err(OnlyCdnNodeProvider) ); } - #[ink::test] fn node_set_params_ok() { let mut ctx = setup_cluster(); @@ -137,7 +141,8 @@ fn node_set_params_ok() { // Change params. let new_cdn_node_params = NodeParams::from("new cdn node params"); set_caller_value(ctx.provider_id0, CONTRACT_FEE_LIMIT); - ctx.contract.cdn_node_set_params(ctx.cdn_node_key0, new_cdn_node_params.clone())?; + ctx.contract + .cdn_node_set_params(ctx.cdn_node_key0, new_cdn_node_params.clone())?; assert!( matches!(get_events().pop().unwrap(), Event::CdnNodeParamsSet(ev) if ev == @@ -157,7 +162,11 @@ fn node_set_params_ok() { fn cdn_node_get_err_if_node_does_not_exist() { let ctx = setup_cluster(); - let bad_cdn_node_key = AccountId::from([0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, 0x9c, 0x76]); + let bad_cdn_node_key = AccountId::from([ + 0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, + 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, + 0x9c, 0x76, + ]); assert_eq!( ctx.contract.cdn_node_get(bad_cdn_node_key), @@ -172,21 +181,20 @@ fn node_get_ok() { assert_eq!( ctx.contract.cdn_node_get(ctx.cdn_node_key1), Ok({ - CdnNodeInfo { - cdn_node_key: ctx.cdn_node_key1, + CdnNodeInfo { + cdn_node_key: ctx.cdn_node_key1, cdn_node: CdnNode { provider_id: ctx.provider_id1, undistributed_payment: 0, - cdn_node_params:ctx.cdn_node_params1, + cdn_node_params: ctx.cdn_node_params1, cluster_id: Some(ctx.cluster_id), status_in_cluster: Some(NodeStatusInCluster::ADDING), - }, + }, } }) ); } - #[ink::test] fn node_list_ok() { let ctx = setup_cluster(); @@ -201,7 +209,7 @@ fn node_list_ok() { undistributed_payment: 0, cluster_id: Some(ctx.cluster_id), status_in_cluster: Some(NodeStatusInCluster::ADDING), - cdn_node_params: ctx.cdn_node_params1.clone() + cdn_node_params: ctx.cdn_node_params1.clone(), }, }; @@ -212,8 +220,8 @@ fn node_list_ok() { undistributed_payment: 0, cluster_id: Some(ctx.cluster_id), status_in_cluster: Some(NodeStatusInCluster::ADDING), - cdn_node_params: ctx.cdn_node_params2.clone() - } + cdn_node_params: ctx.cdn_node_params2.clone(), + }, }; let count = 3; @@ -251,7 +259,11 @@ fn node_list_ok() { (vec![cdn_node2.clone()], count) ); - let not_provider_id= AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_provider_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); assert_eq!( ctx.contract.cdn_node_list(1, 100, Some(not_provider_id)), diff --git a/bucket/ddc_bucket/tests/test_cluster.rs b/bucket/ddc_bucket/tests/test_cluster.rs index 94584e56..5d5ef9da 100644 --- a/bucket/ddc_bucket/tests/test_cluster.rs +++ b/bucket/ddc_bucket/tests/test_cluster.rs @@ -1,31 +1,46 @@ use ink_lang as ink; -use crate::ddc_bucket::Error::*; -use crate::ddc_bucket::*; -use cdn_node::{entity::*}; use super::env_utils::*; use super::setup_utils::*; - +use crate::ddc_bucket::Error::*; +use crate::ddc_bucket::*; +use cdn_node::entity::*; #[ink::test] fn cluster_create_ok() { let ctx = setup_cluster(); let providers_ids = &[ctx.provider_id0, ctx.provider_id1, ctx.provider_id2]; let node_keys = &[ctx.node_key0, ctx.node_key1, ctx.node_key2]; - let v_nodes = &[ctx.v_nodes0.clone(), ctx.v_nodes1.clone(), ctx.v_nodes2.clone()]; + let v_nodes = &[ + ctx.v_nodes0.clone(), + ctx.v_nodes1.clone(), + ctx.v_nodes2.clone(), + ]; let cdn_node_keys = &[ctx.cdn_node_key0, ctx.cdn_node_key1, ctx.cdn_node_key2]; - let node_params = &[ctx.node_params0.clone(), ctx.node_params1.clone(), ctx.node_params2.clone()]; - let cdn_node_params = &[ctx.cdn_node_params0.clone(), ctx.cdn_node_params1.clone(), ctx.cdn_node_params2.clone()]; - let rent_v_node_per_month = &[ctx.rent_v_node_per_month0.clone(), ctx.rent_v_node_per_month1.clone(), ctx.rent_v_node_per_month2.clone()]; - + let node_params = &[ + ctx.node_params0.clone(), + ctx.node_params1.clone(), + ctx.node_params2.clone(), + ]; + let cdn_node_params = &[ + ctx.cdn_node_params0.clone(), + ctx.cdn_node_params1.clone(), + ctx.cdn_node_params2.clone(), + ]; + let rent_v_node_per_month = &[ + ctx.rent_v_node_per_month0.clone(), + ctx.rent_v_node_per_month1.clone(), + ctx.rent_v_node_per_month2.clone(), + ]; + assert_eq!(ctx.cluster_id, 0, "cluster_id must start at 0"); // Check cluster Storage nodes - + let node0 = ctx.contract.node_get(ctx.node_key0)?; let v_nodes0 = ctx.contract.get_v_nodes_by_node(ctx.node_key0); - let v_nodes0_len : u32 = v_nodes0.len().try_into().unwrap(); + let v_nodes0_len: u32 = v_nodes0.len().try_into().unwrap(); assert_eq!( node0, @@ -45,7 +60,7 @@ fn cluster_create_ok() { let node1 = ctx.contract.node_get(ctx.node_key1)?; let v_nodes1 = ctx.contract.get_v_nodes_by_node(ctx.node_key1); - let v_nodes1_len : u32 = v_nodes1.len().try_into().unwrap(); + let v_nodes1_len: u32 = v_nodes1.len().try_into().unwrap(); assert_eq!( node1, @@ -65,7 +80,7 @@ fn cluster_create_ok() { let node2 = ctx.contract.node_get(ctx.node_key2)?; let v_nodes2 = ctx.contract.get_v_nodes_by_node(ctx.node_key2); - let v_nodes2_len : u32 = v_nodes2.len().try_into().unwrap(); + let v_nodes2_len: u32 = v_nodes2.len().try_into().unwrap(); assert_eq!( node2, @@ -84,11 +99,10 @@ fn cluster_create_ok() { ); // Check cluster CDN nodes - + let cdn_node0 = ctx.contract.cdn_node_get(ctx.cdn_node_key0)?; assert_eq!( - cdn_node0, CdnNodeInfo { cdn_node_key: ctx.cdn_node_key0, @@ -133,14 +147,12 @@ fn cluster_create_ok() { }, } ); - // Check the cluster - + let cluster = ctx.contract.cluster_get(ctx.cluster_id)?; let cluster_v_nodes = ctx.contract.get_v_nodes_by_cluster(ctx.cluster_id); - let total_rent = - ctx.rent_v_node_per_month0 * v_nodes0_len as Balance + let total_rent = ctx.rent_v_node_per_month0 * v_nodes0_len as Balance + ctx.rent_v_node_per_month1 * v_nodes1_len as Balance + ctx.rent_v_node_per_month2 * v_nodes2_len as Balance; @@ -164,14 +176,14 @@ fn cluster_create_ok() { } ); - // Check emitted events let mut events = get_events(); events.reverse(); // Work with pop(). // Storage node created event for i in 0..3 { - assert!(matches!(events.pop().unwrap(), Event::NodeCreated(ev) if ev == + assert!( + matches!(events.pop().unwrap(), Event::NodeCreated(ev) if ev == NodeCreated { node_key: node_keys[i], provider_id: providers_ids[i], @@ -183,7 +195,8 @@ fn cluster_create_ok() { // CDN node created event for i in 0..3 { - assert!(matches!(events.pop().unwrap(), Event::CdnNodeCreated(ev) if ev == + assert!( + matches!(events.pop().unwrap(), Event::CdnNodeCreated(ev) if ev == CdnNodeCreated { cdn_node_key: cdn_node_keys[i], provider_id: providers_ids[i], @@ -196,9 +209,9 @@ fn cluster_create_ok() { // Cluster created event assert!( matches!(events.pop().unwrap(), Event::ClusterCreated(ev) if ev == - ClusterCreated { - cluster_id: ctx.cluster_id, - manager_id: ctx.manager_id, + ClusterCreated { + cluster_id: ctx.cluster_id, + manager_id: ctx.manager_id, cluster_params: ctx.cluster_params.clone() }) ); @@ -207,16 +220,17 @@ fn cluster_create_ok() { for provider_id in providers_ids { assert!( matches!(events.pop().unwrap(), Event::PermissionGranted(ev) if ev == - PermissionGranted { - account_id: ctx.manager_id, - permission: Permission::ClusterManagerTrustedBy(*provider_id) + PermissionGranted { + account_id: ctx.manager_id, + permission: Permission::ClusterManagerTrustedBy(*provider_id) }) ); } // Cluster storage node added event for i in 0..3 { - assert!(matches!(events.pop().unwrap(), Event::ClusterNodeAdded(ev) if ev == + assert!( + matches!(events.pop().unwrap(), Event::ClusterNodeAdded(ev) if ev == ClusterNodeAdded { cluster_id: ctx.cluster_id, node_key: node_keys[i], @@ -225,188 +239,191 @@ fn cluster_create_ok() { ); } - // Cluster cdn node added event for i in 0..3 { - assert!(matches!(events.pop().unwrap(), Event::ClusterCdnNodeAdded(ev) if ev == + assert!( + matches!(events.pop().unwrap(), Event::ClusterCdnNodeAdded(ev) if ev == ClusterCdnNodeAdded { cluster_id: ctx.cluster_id, cdn_node_key: cdn_node_keys[i] }) ); } - - assert_eq!(events.len(), 0, "All events must be checked"); + assert_eq!(events.len(), 0, "All events must be checked"); } - #[ink::test] fn cluster_add_node_err_if_node_is_in_cluster() { let mut ctx = setup_cluster(); - let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + let another_manager_id = AccountId::from([ + 0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, + 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, + 0x58, 0x7a, + ]); set_balance(another_manager_id, 1000 * TOKEN); set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - let another_cluster_id = ctx.contract.cluster_create( - ClusterParams::from("{}"), - 10 - )?; + let another_cluster_id = ctx.contract.cluster_create(ClusterParams::from("{}"), 10)?; assert_eq!( - ctx.contract.cluster_add_node( - another_cluster_id, - ctx.node_key1, - ctx.v_nodes1, - ), + ctx.contract + .cluster_add_node(another_cluster_id, ctx.node_key1, ctx.v_nodes1,), Err(NodeIsAddedToCluster(ctx.cluster_id)) ); } - #[ink::test] fn cluster_add_node_err_if_not_trusted_manager() { let mut ctx = setup_cluster(); - let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + let another_manager_id = AccountId::from([ + 0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, + 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, + 0x58, 0x7a, + ]); set_balance(another_manager_id, 1000 * TOKEN); set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - let another_cluster_id = ctx.contract.cluster_create( - ClusterParams::from("{}"), - 10 - )?; + let another_cluster_id = ctx.contract.cluster_create(ClusterParams::from("{}"), 10)?; - let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + let new_provider_id = AccountId::from([ + 0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, + 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, + 0xcb, 0x5a, + ]); set_balance(new_provider_id, 1000 * TOKEN); - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - let new_node_key = ctx.contract.node_create( - new_node_key, - NodeParams::from("new_node"), - 1000, - 100 - )?; + let new_node_key = + ctx.contract + .node_create(new_node_key, NodeParams::from("new_node"), 1000, 100)?; let new_v_nodes: Vec = vec![10, 11, 12]; set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); assert_eq!( - ctx.contract.cluster_add_node( - another_cluster_id, - new_node_key, - new_v_nodes, - ), + ctx.contract + .cluster_add_node(another_cluster_id, new_node_key, new_v_nodes,), Err(OnlyTrustedClusterManager) ); } - #[ink::test] fn cluster_add_node_err_if_not_cluster_manager() { let mut ctx = setup_cluster(); - let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + let another_manager_id = AccountId::from([ + 0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, + 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, + 0x58, 0x7a, + ]); set_balance(another_manager_id, 1000 * TOKEN); set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - let another_cluster_id = ctx.contract.cluster_create( - ClusterParams::from("{}"), - 10 - )?; + let another_cluster_id = ctx.contract.cluster_create(ClusterParams::from("{}"), 10)?; - let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + let new_provider_id = AccountId::from([ + 0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, + 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, + 0xcb, 0x5a, + ]); set_balance(new_provider_id, 1000 * TOKEN); - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.node_create( - new_node_key, - NodeParams::from("new_node"), - 1000, - 100 - )?; - - let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + ctx.contract + .node_create(new_node_key, NodeParams::from("new_node"), 1000, 100)?; + + let not_manager_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); set_balance(not_manager_id, 1000 * TOKEN); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.grant_trusted_manager_permission(not_manager_id)?; + ctx.contract + .grant_trusted_manager_permission(not_manager_id)?; let new_v_nodes: Vec = vec![10, 11, 12]; set_caller_value(not_manager_id, CONTRACT_FEE_LIMIT); assert_eq!( - ctx.contract.cluster_add_node( - another_cluster_id, - new_node_key, - new_v_nodes, - ), + ctx.contract + .cluster_add_node(another_cluster_id, new_node_key, new_v_nodes,), Err(OnlyClusterManager) ); } - #[ink::test] fn cluster_add_node_err_if_no_v_nodes() { let mut ctx = setup_cluster(); - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); set_caller_value(ctx.provider_id0, 10); - ctx.contract.node_create( - new_node_key, - NodeParams::from("new_node"), - 1000000000, - 1 - )?; + ctx.contract + .node_create(new_node_key, NodeParams::from("new_node"), 1000000000, 1)?; set_caller_value(ctx.manager_id, 10); assert_eq!( - ctx.contract.cluster_add_node( - ctx.cluster_id, - new_node_key, - vec![], - ), + ctx.contract + .cluster_add_node(ctx.cluster_id, new_node_key, vec![],), Err(AtLeastOneVNodeHasToBeAssigned(ctx.cluster_id, new_node_key)) ); } - #[ink::test] fn cluster_add_node_err_if_v_nodes_exceeds_limit() { let mut ctx = setup_cluster(); - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); set_caller_value(ctx.provider_id0, 10); - ctx.contract.node_create( - new_node_key, - NodeParams::from("new_node"), - 1000000000, - 1 - )?; + ctx.contract + .node_create(new_node_key, NodeParams::from("new_node"), 1000000000, 1)?; set_caller_value(ctx.manager_id, 10); assert_eq!( - ctx.contract.cluster_add_node( - ctx.cluster_id, - new_node_key, - vec![100; 1801], - ), + ctx.contract + .cluster_add_node(ctx.cluster_id, new_node_key, vec![100; 1801],), Err(VNodesSizeExceedsLimit) ); } - #[ink::test] fn cluster_add_node_ok() { let mut ctx = setup_cluster(); - let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + let new_provider_id = AccountId::from([ + 0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, + 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, + 0xcb, 0x5a, + ]); set_balance(new_provider_id, 1000 * TOKEN); - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); let new_node_rent_v_node_per_month = 100; let new_node_params = NodeParams::from("new_node"); let new_node_capacity = 1000; @@ -416,39 +433,35 @@ fn cluster_add_node_ok() { new_node_key, new_node_params.clone(), new_node_capacity, - new_node_rent_v_node_per_month + new_node_rent_v_node_per_month, )?; assert!( matches!(get_events().pop().unwrap(), Event::NodeCreated(ev) if ev == - NodeCreated { - node_key: new_node_key, - provider_id: new_provider_id, - rent_v_node_per_month: new_node_rent_v_node_per_month, - node_params: new_node_params.clone(), - }) + NodeCreated { + node_key: new_node_key, + provider_id: new_provider_id, + rent_v_node_per_month: new_node_rent_v_node_per_month, + node_params: new_node_params.clone(), + }) ); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.grant_trusted_manager_permission(ctx.manager_id)?; + ctx.contract + .grant_trusted_manager_permission(ctx.manager_id)?; - assert!( - matches!( - get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == - PermissionGranted { - account_id: ctx.manager_id, - permission: Permission::ClusterManagerTrustedBy(new_provider_id) - } - ) - ); + assert!(matches!( + get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == + PermissionGranted { + account_id: ctx.manager_id, + permission: Permission::ClusterManagerTrustedBy(new_provider_id) + } + )); let new_v_nodes: Vec = vec![10, 11, 12]; set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); - ctx.contract.cluster_add_node( - ctx.cluster_id, - new_node_key, - new_v_nodes.clone() - )?; + ctx.contract + .cluster_add_node(ctx.cluster_id, new_node_key, new_v_nodes.clone())?; assert!( matches!(get_events().pop().unwrap(), Event::ClusterNodeAdded(ev) if ev == @@ -459,18 +472,13 @@ fn cluster_add_node_ok() { }) ); - let _nodes_keys = vec![ - ctx.node_key0, - ctx.node_key1, - ctx.node_key2, - new_node_key, - ]; + let _nodes_keys = vec![ctx.node_key0, ctx.node_key1, ctx.node_key2, new_node_key]; let _cluster_v_nodes = vec![ ctx.v_nodes0, ctx.v_nodes1, ctx.v_nodes2, - new_v_nodes.clone() + new_v_nodes.clone(), ]; let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; @@ -487,69 +495,68 @@ fn cluster_add_node_ok() { free_resource: new_node_capacity, node_params: new_node_params, cluster_id: Some(ctx.cluster_id), - status_in_cluster: Some(NodeStatusInCluster::ADDING) + status_in_cluster: Some(NodeStatusInCluster::ADDING), }, - v_nodes: new_v_nodes + v_nodes: new_v_nodes, }; assert!(matches!(node_info, _expected_node_info)); } - #[ink::test] fn cluster_remove_node_err_if_node_is_not_in_cluster() { let mut ctx = setup_cluster(); - let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + let new_provider_id = AccountId::from([ + 0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, + 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, + 0xcb, 0x5a, + ]); set_balance(new_provider_id, 1000 * TOKEN); - let another_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let another_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.node_create( - another_node_key, - NodeParams::from("new_node"), - 1000, - 100 - )?; + ctx.contract + .node_create(another_node_key, NodeParams::from("new_node"), 1000, 100)?; set_caller(ctx.manager_id); assert_eq!( - ctx.contract.cluster_remove_node( - ctx.cluster_id, - another_node_key, - ), + ctx.contract + .cluster_remove_node(ctx.cluster_id, another_node_key,), Err(NodeIsNotAddedToCluster(ctx.cluster_id)) ); } - #[ink::test] fn cluster_remove_node_err_if_not_manager_and_not_provider() { let mut ctx = setup_cluster(); - let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_manager_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); set_balance(not_manager_id, 1000 * TOKEN); set_caller(not_manager_id); assert_eq!( - ctx.contract.cluster_remove_node( - ctx.cluster_id, - ctx.node_key1, - ), + ctx.contract + .cluster_remove_node(ctx.cluster_id, ctx.node_key1,), Err(OnlyClusterManagerOrNodeProvider) ); } - #[ink::test] fn cluster_remove_node_ok_if_node_provider() { let mut ctx = setup_cluster(); set_caller(ctx.manager_id); - ctx.contract.cluster_remove_node( - ctx.cluster_id, - ctx.node_key1 - )?; + ctx.contract + .cluster_remove_node(ctx.cluster_id, ctx.node_key1)?; assert!( matches!(get_events().pop().unwrap(), Event::ClusterNodeRemoved(ev) if ev == @@ -559,15 +566,9 @@ fn cluster_remove_node_ok_if_node_provider() { }) ); - let _nodes_keys = vec![ - ctx.node_key0, - ctx.node_key2, - ]; + let _nodes_keys = vec![ctx.node_key0, ctx.node_key2]; - let _cluster_v_nodes = vec![ - ctx.v_nodes0.clone(), - ctx.v_nodes2, - ]; + let _cluster_v_nodes = vec![ctx.v_nodes0.clone(), ctx.v_nodes2]; let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; cluster_info.cluster_v_nodes.sort(); @@ -575,7 +576,7 @@ fn cluster_remove_node_ok_if_node_provider() { assert!(matches!(cluster_info.cluster_v_nodes, _cluster_v_nodes)); let node_info = ctx.contract.node_get(ctx.node_key1)?; - let v_nodes0_len : u32 = ctx.v_nodes0.len().try_into().unwrap(); + let v_nodes0_len: u32 = ctx.v_nodes0.len().try_into().unwrap(); let _expected_node_info = NodeInfo { node_key: ctx.node_key1, node: Node { @@ -584,24 +585,20 @@ fn cluster_remove_node_ok_if_node_provider() { free_resource: ctx.node_capacity1 - ctx.resource_per_v_node * v_nodes0_len, node_params: ctx.node_params1, cluster_id: None, - status_in_cluster: None + status_in_cluster: None, }, - v_nodes: Vec::new() + v_nodes: Vec::new(), }; assert!(matches!(node_info, _expected_node_info)); - } - #[ink::test] fn cluster_remove_node_ok_if_cluster_manager() { let mut ctx = setup_cluster(); set_caller(ctx.provider_id2); - ctx.contract.cluster_remove_node( - ctx.cluster_id, - ctx.node_key2 - )?; + ctx.contract + .cluster_remove_node(ctx.cluster_id, ctx.node_key2)?; assert!( matches!(get_events().pop().unwrap(), Event::ClusterNodeRemoved(ev) if ev == @@ -611,24 +608,17 @@ fn cluster_remove_node_ok_if_cluster_manager() { }) ); - let _nodes_keys = vec![ - ctx.node_key0, - ctx.node_key1, - ]; + let _nodes_keys = vec![ctx.node_key0, ctx.node_key1]; - let _cluster_v_nodes = vec![ - ctx.v_nodes0, - ctx.v_nodes1, - ]; + let _cluster_v_nodes = vec![ctx.v_nodes0, ctx.v_nodes1]; let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; cluster_info.cluster_v_nodes.sort(); assert!(matches!(cluster_info.cluster.nodes_keys, _nodes_keys)); - assert!(matches!(cluster_info.cluster_v_nodes, _cluster_v_nodes - )); + assert!(matches!(cluster_info.cluster_v_nodes, _cluster_v_nodes)); let node_info = ctx.contract.node_get(ctx.node_key2)?; - let v_nodes2_len : u32 = ctx.v_nodes2.len().try_into().unwrap(); + let v_nodes2_len: u32 = ctx.v_nodes2.len().try_into().unwrap(); let _expected_node_info = NodeInfo { node_key: ctx.node_key2, @@ -638,158 +628,170 @@ fn cluster_remove_node_ok_if_cluster_manager() { free_resource: ctx.node_capacity2 - ctx.resource_per_v_node * v_nodes2_len, node_params: ctx.node_params2, cluster_id: None, - status_in_cluster: None + status_in_cluster: None, }, - v_nodes: Vec::new() + v_nodes: Vec::new(), }; assert!(matches!(node_info, _expected_node_info)); - } - #[ink::test] fn cluster_add_cdn_node_err_if_cdn_node_is_in_cluster() { let mut ctx = setup_cluster(); - let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + let another_manager_id = AccountId::from([ + 0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, + 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, + 0x58, 0x7a, + ]); set_balance(another_manager_id, 1000 * TOKEN); set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - let another_cluster_id = ctx.contract.cluster_create( - ClusterParams::from("{}"), - 10 - )?; + let another_cluster_id = ctx.contract.cluster_create(ClusterParams::from("{}"), 10)?; assert_eq!( - ctx.contract.cluster_add_cdn_node( - another_cluster_id, - ctx.cdn_node_key1, - ), + ctx.contract + .cluster_add_cdn_node(another_cluster_id, ctx.cdn_node_key1,), Err(CdnNodeIsAddedToCluster(ctx.cluster_id)) ); } - #[ink::test] fn cluster_add_cdn_node_err_if_not_trusted_manager() { let mut ctx = setup_cluster(); - let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + let another_manager_id = AccountId::from([ + 0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, + 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, + 0x58, 0x7a, + ]); set_balance(another_manager_id, 1000 * TOKEN); set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - let another_cluster_id = ctx.contract.cluster_create( - ClusterParams::from("{}"), - 10 - )?; + let another_cluster_id = ctx.contract.cluster_create(ClusterParams::from("{}"), 10)?; - let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + let new_provider_id = AccountId::from([ + 0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, + 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, + 0xcb, 0x5a, + ]); set_balance(new_provider_id, 1000 * TOKEN); - let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_cdn_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.cdn_node_create( - new_cdn_node_key, - CdnNodeParams::from("new_cdn_node"), - )?; + ctx.contract + .cdn_node_create(new_cdn_node_key, CdnNodeParams::from("new_cdn_node"))?; set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); assert_eq!( - ctx.contract.cluster_add_cdn_node( - another_cluster_id, - new_cdn_node_key, - ), + ctx.contract + .cluster_add_cdn_node(another_cluster_id, new_cdn_node_key,), Err(OnlyTrustedClusterManager) ); } - #[ink::test] fn cluster_add_cdn_node_err_if_not_cluster_manager() { let mut ctx = setup_cluster(); - let another_manager_id = AccountId::from([0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, 0x58, 0x7a]); + let another_manager_id = AccountId::from([ + 0x54, 0x66, 0x76, 0x6c, 0xf6, 0x17, 0x70, 0xcf, 0x5d, 0x70, 0x6c, 0x55, 0x4d, 0xd4, 0xb7, + 0xf8, 0x83, 0xe6, 0x70, 0x06, 0xea, 0x4c, 0x05, 0x89, 0x16, 0x32, 0x79, 0x79, 0xbb, 0x85, + 0x58, 0x7a, + ]); set_balance(another_manager_id, 1000 * TOKEN); set_caller_value(another_manager_id, CONTRACT_FEE_LIMIT); - let another_cluster_id = ctx.contract.cluster_create( - ClusterParams::from("{}"), - 10 - )?; + let another_cluster_id = ctx.contract.cluster_create(ClusterParams::from("{}"), 10)?; - let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + let new_provider_id = AccountId::from([ + 0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, + 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, + 0xcb, 0x5a, + ]); set_balance(new_provider_id, 1000 * TOKEN); - let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_cdn_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.cdn_node_create( - new_cdn_node_key, - CdnNodeParams::from("new_cdn_node"), - )?; - - let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + ctx.contract + .cdn_node_create(new_cdn_node_key, CdnNodeParams::from("new_cdn_node"))?; + + let not_manager_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); set_balance(not_manager_id, 1000 * TOKEN); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.grant_trusted_manager_permission(not_manager_id)?; + ctx.contract + .grant_trusted_manager_permission(not_manager_id)?; set_caller_value(not_manager_id, CONTRACT_FEE_LIMIT); assert_eq!( - ctx.contract.cluster_add_cdn_node( - another_cluster_id, - new_cdn_node_key, - ), + ctx.contract + .cluster_add_cdn_node(another_cluster_id, new_cdn_node_key,), Err(OnlyClusterManager) ); } - #[ink::test] fn cluster_add_cdn_node_ok() { let mut ctx = setup_cluster(); - let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + let new_provider_id = AccountId::from([ + 0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, + 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, + 0xcb, 0x5a, + ]); set_balance(new_provider_id, 1000 * TOKEN); - let new_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_cdn_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); let new_cdn_node_params = CdnNodeParams::from("new_cdn_node"); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.cdn_node_create( - new_cdn_node_key, - new_cdn_node_params.clone(), - )?; + ctx.contract + .cdn_node_create(new_cdn_node_key, new_cdn_node_params.clone())?; assert!( matches!(get_events().pop().unwrap(), Event::CdnNodeCreated(ev) if ev == - CdnNodeCreated { - cdn_node_key: new_cdn_node_key, - provider_id: new_provider_id, - cdn_node_params: new_cdn_node_params.clone(), - undistributed_payment: 0 - }) + CdnNodeCreated { + cdn_node_key: new_cdn_node_key, + provider_id: new_provider_id, + cdn_node_params: new_cdn_node_params.clone(), + undistributed_payment: 0 + }) ); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.grant_trusted_manager_permission(ctx.manager_id)?; + ctx.contract + .grant_trusted_manager_permission(ctx.manager_id)?; - assert!( - matches!( - get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == - PermissionGranted { - account_id: ctx.manager_id, - permission: Permission::ClusterManagerTrustedBy(new_provider_id) - } - ) - ); + assert!(matches!( + get_events().pop().unwrap(), Event::PermissionGranted(ev) if ev == + PermissionGranted { + account_id: ctx.manager_id, + permission: Permission::ClusterManagerTrustedBy(new_provider_id) + } + )); set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); - ctx.contract.cluster_add_cdn_node( - ctx.cluster_id, - new_cdn_node_key, - )?; + ctx.contract + .cluster_add_cdn_node(ctx.cluster_id, new_cdn_node_key)?; assert!( matches!(get_events().pop().unwrap(), Event::ClusterCdnNodeAdded(ev) if ev == @@ -807,7 +809,10 @@ fn cluster_add_cdn_node_ok() { ]; let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; - assert!(matches!(cluster_info.cluster.cdn_nodes_keys, _cdn_nodes_keys)); + assert!(matches!( + cluster_info.cluster.cdn_nodes_keys, + _cdn_nodes_keys + )); let cdn_node_info = ctx.contract.cdn_node_get(new_cdn_node_key)?; let _expected_cdn_node_info = CdnNodeInfo { @@ -817,66 +822,67 @@ fn cluster_add_cdn_node_ok() { undistributed_payment: 0, cdn_node_params: new_cdn_node_params, cluster_id: Some(ctx.cluster_id), - status_in_cluster: Some(NodeStatusInCluster::ADDING) + status_in_cluster: Some(NodeStatusInCluster::ADDING), }, }; assert!(matches!(cdn_node_info, _expected_cdn_node_info)); } - #[ink::test] fn cluster_remove_cdn_node_err_if_cdn_node_is_not_in_cluster() { let mut ctx = setup_cluster(); - let new_provider_id = AccountId::from([0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, 0xcb, 0x5a]); + let new_provider_id = AccountId::from([ + 0x3c, 0x08, 0xea, 0xa6, 0x89, 0xdf, 0x45, 0x2b, 0x77, 0xa1, 0xa5, 0x6b, 0x83, 0x10, 0x1e, + 0x31, 0x06, 0xc9, 0xc7, 0xaf, 0xb3, 0xe9, 0xfd, 0x6f, 0xa6, 0x2b, 0x50, 0x00, 0xf6, 0xeb, + 0xcb, 0x5a, + ]); set_balance(new_provider_id, 1000 * TOKEN); - let another_cdn_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let another_cdn_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); set_caller_value(new_provider_id, CONTRACT_FEE_LIMIT); - ctx.contract.cdn_node_create( - another_cdn_node_key, - CdnNodeParams::from("new_cdn_node") - )?; + ctx.contract + .cdn_node_create(another_cdn_node_key, CdnNodeParams::from("new_cdn_node"))?; set_caller(ctx.manager_id); assert_eq!( - ctx.contract.cluster_remove_cdn_node( - ctx.cluster_id, - another_cdn_node_key, - ), + ctx.contract + .cluster_remove_cdn_node(ctx.cluster_id, another_cdn_node_key,), Err(CdnNodeIsNotAddedToCluster(ctx.cluster_id)) ); } - #[ink::test] fn cluster_remove_cdn_node_err_if_not_manager_and_not_provider() { let mut ctx = setup_cluster(); - let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_manager_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); set_balance(not_manager_id, 1000 * TOKEN); set_caller(not_manager_id); assert_eq!( - ctx.contract.cluster_remove_cdn_node( - ctx.cluster_id, - ctx.cdn_node_key1, - ), + ctx.contract + .cluster_remove_cdn_node(ctx.cluster_id, ctx.cdn_node_key1,), Err(OnlyClusterManagerOrCdnNodeProvider) ); } - #[ink::test] fn cluster_remove_cdn_node_ok_if_cdn_node_provider() { let mut ctx = setup_cluster(); set_caller(ctx.manager_id); - ctx.contract.cluster_remove_cdn_node( - ctx.cluster_id, - ctx.cdn_node_key1 - )?; + ctx.contract + .cluster_remove_cdn_node(ctx.cluster_id, ctx.cdn_node_key1)?; assert!( matches!(get_events().pop().unwrap(), Event::ClusterCdnNodeRemoved(ev) if ev == @@ -886,13 +892,13 @@ fn cluster_remove_cdn_node_ok_if_cdn_node_provider() { }) ); - let _cdn_nodes_keys = vec![ - ctx.cdn_node_key0, - ctx.cdn_node_key2, - ]; + let _cdn_nodes_keys = vec![ctx.cdn_node_key0, ctx.cdn_node_key2]; let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; - assert!(matches!(cluster_info.cluster.cdn_nodes_keys, _cdn_nodes_keys)); + assert!(matches!( + cluster_info.cluster.cdn_nodes_keys, + _cdn_nodes_keys + )); let cdn_node_info = ctx.contract.cdn_node_get(ctx.cdn_node_key1)?; let _expected_cdn_node_info = CdnNodeInfo { @@ -902,23 +908,19 @@ fn cluster_remove_cdn_node_ok_if_cdn_node_provider() { undistributed_payment: 0, cdn_node_params: ctx.cdn_node_params1, cluster_id: None, - status_in_cluster: None + status_in_cluster: None, }, }; assert!(matches!(cdn_node_info, _expected_cdn_node_info)); - } - #[ink::test] fn cluster_remove_cdn_node_ok_if_cluster_manager() { let mut ctx = setup_cluster(); set_caller(ctx.provider_id2); - ctx.contract.cluster_remove_cdn_node( - ctx.cluster_id, - ctx.cdn_node_key2 - )?; + ctx.contract + .cluster_remove_cdn_node(ctx.cluster_id, ctx.cdn_node_key2)?; assert!( matches!(get_events().pop().unwrap(), Event::ClusterCdnNodeRemoved(ev) if ev == @@ -928,13 +930,13 @@ fn cluster_remove_cdn_node_ok_if_cluster_manager() { }) ); - let _cdn_nodes_keys = vec![ - ctx.cdn_node_key0, - ctx.cdn_node_key1, - ]; + let _cdn_nodes_keys = vec![ctx.cdn_node_key0, ctx.cdn_node_key1]; let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; - assert!(matches!(cluster_info.cluster.cdn_nodes_keys, _cdn_nodes_keys)); + assert!(matches!( + cluster_info.cluster.cdn_nodes_keys, + _cdn_nodes_keys + )); let cdn_node_info = ctx.contract.cdn_node_get(ctx.cdn_node_key2)?; let _expected_cdn_node_info = CdnNodeInfo { @@ -944,33 +946,33 @@ fn cluster_remove_cdn_node_ok_if_cluster_manager() { undistributed_payment: 0, cdn_node_params: ctx.cdn_node_params2, cluster_id: None, - status_in_cluster: None + status_in_cluster: None, }, }; assert!(matches!(cdn_node_info, _expected_cdn_node_info)); } - #[ink::test] fn cluster_set_params_err_if_not_cluster_manager() { let ctx = &mut setup_cluster(); - let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_manager_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); set_balance(not_manager_id, 1000 * TOKEN); // Change params. let new_cluster_params = NodeParams::from("new cluster params"); set_caller_value(not_manager_id, CONTRACT_FEE_LIMIT); assert_eq!( - ctx.contract.cluster_set_params( - ctx.cluster_id, - new_cluster_params - ), + ctx.contract + .cluster_set_params(ctx.cluster_id, new_cluster_params), Err(OnlyClusterManager) ); } - #[ink::test] fn cluster_set_params_ok() { let mut ctx = setup_cluster(); @@ -978,155 +980,139 @@ fn cluster_set_params_ok() { // Change params. let new_cluster_params = NodeParams::from("new cluster params"); set_caller_value(ctx.manager_id, CONTRACT_FEE_LIMIT); - ctx.contract.cluster_set_params(ctx.cluster_id, new_cluster_params.clone())?; + ctx.contract + .cluster_set_params(ctx.cluster_id, new_cluster_params.clone())?; // Check the changed params. let cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; assert_eq!(cluster_info.cluster.cluster_params, new_cluster_params); } - #[ink::test] fn cluster_replace_node_err_if_not_cluster_manager() { let mut ctx = setup_cluster(); - let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_manager_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); set_caller_value(not_manager_id, 0); // Reassign a vnode from node1 to node2. assert_eq!( - ctx.contract.cluster_replace_node( - ctx.cluster_id, - vec![1, 2, 3], - ctx.node_key2 - ), + ctx.contract + .cluster_replace_node(ctx.cluster_id, vec![1, 2, 3], ctx.node_key2), Err(OnlyClusterManager) ); } - #[ink::test] fn cluster_replace_node_err_if_node_does_not_exist() { let mut ctx = setup_cluster(); - let bad_node_key = AccountId::from([0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, 0x9c, 0x76]); + let bad_node_key = AccountId::from([ + 0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, + 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, + 0x9c, 0x76, + ]); set_caller(ctx.manager_id); assert_eq!( - ctx.contract.cluster_replace_node( - ctx.cluster_id, - vec![1, 2, 3], - bad_node_key - ), + ctx.contract + .cluster_replace_node(ctx.cluster_id, vec![1, 2, 3], bad_node_key), Err(NodeDoesNotExist) ); } - #[ink::test] fn cluster_replace_node_err_if_no_v_nodes() { let mut ctx = setup_cluster(); assert_eq!( - ctx.contract.cluster_replace_node( - ctx.cluster_id, - vec![], + ctx.contract + .cluster_replace_node(ctx.cluster_id, vec![], ctx.node_key2), + Err(AtLeastOneVNodeHasToBeAssigned( + ctx.cluster_id, ctx.node_key2 - ), - Err(AtLeastOneVNodeHasToBeAssigned(ctx.cluster_id, ctx.node_key2)) + )) ); } - #[ink::test] fn cluster_replace_node_err_if_node_is_not_in_cluster() { let mut ctx = setup_cluster(); - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); set_caller_value(ctx.provider_id0, 10); - ctx.contract.node_create( - new_node_key, - NodeParams::from("new_node"), - 1000000000, - 1 - )?; + ctx.contract + .node_create(new_node_key, NodeParams::from("new_node"), 1000000000, 1)?; set_caller_value(ctx.manager_id, 10); assert_eq!( - ctx.contract.cluster_replace_node( - ctx.cluster_id, - vec![1, 3], - new_node_key - ), + ctx.contract + .cluster_replace_node(ctx.cluster_id, vec![1, 3], new_node_key), Err(NodeIsNotAddedToCluster(ctx.cluster_id)) ); } - #[ink::test] fn cluster_replace_node_err_if_v_nodes_exceeds_limit() { let mut ctx = setup_cluster(); - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); set_caller_value(ctx.provider_id0, 10); - ctx.contract.node_create( - new_node_key, - NodeParams::from("new_node"), - 1000000000, - 1 - )?; + ctx.contract + .node_create(new_node_key, NodeParams::from("new_node"), 1000000000, 1)?; set_caller_value(ctx.manager_id, 10); - ctx.contract.cluster_add_node( - ctx.cluster_id, - new_node_key, - vec![100], - )?; + ctx.contract + .cluster_add_node(ctx.cluster_id, new_node_key, vec![100])?; let v_nodes: Vec = vec![100; 1801]; assert_eq!( - ctx.contract.cluster_replace_node( - ctx.cluster_id, - v_nodes, - new_node_key - ), + ctx.contract + .cluster_replace_node(ctx.cluster_id, v_nodes, new_node_key), Err(VNodesSizeExceedsLimit) ); } - #[ink::test] fn cluster_replace_node_err_if_old_node_stays_without_v_nodes() { let mut ctx = setup_cluster(); assert_eq!( - ctx.contract.cluster_replace_node( - ctx.cluster_id, - vec![1, 2, 3], - ctx.node_key2 - ), - Err(AtLeastOneVNodeHasToBeAssigned(ctx.cluster_id, ctx.node_key0)) + ctx.contract + .cluster_replace_node(ctx.cluster_id, vec![1, 2, 3], ctx.node_key2), + Err(AtLeastOneVNodeHasToBeAssigned( + ctx.cluster_id, + ctx.node_key0 + )) ); } - #[ink::test] fn cluster_replace_node_ok() { let mut ctx = setup_cluster(); set_caller(ctx.manager_id); // Reassign a vnode from node0 to node2 - let v_nodes_to_reasign: Vec:: = vec![1, 3]; - ctx.contract.cluster_replace_node( - ctx.cluster_id, - v_nodes_to_reasign.clone(), - ctx.node_key2 - )?; + let v_nodes_to_reasign: Vec = vec![1, 3]; + ctx.contract + .cluster_replace_node(ctx.cluster_id, v_nodes_to_reasign.clone(), ctx.node_key2)?; // Check the last event let ev = get_events().pop().unwrap(); assert!(matches!(ev, Event::ClusterNodeReplaced(ev) if ev == - ClusterNodeReplaced { - cluster_id: ctx.cluster_id, + ClusterNodeReplaced { + cluster_id: ctx.cluster_id, node_key: ctx.node_key2, v_nodes: v_nodes_to_reasign.clone(), } @@ -1141,7 +1127,10 @@ fn cluster_replace_node_ok() { let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; cluster_info.cluster_v_nodes.sort(); - assert_eq!(&cluster_info.cluster_v_nodes, &cluster_v_nodes, "a v_node must be replaced"); + assert_eq!( + &cluster_info.cluster_v_nodes, &cluster_v_nodes, + "a v_node must be replaced" + ); let mut v_nodes0 = ctx.contract.get_v_nodes_by_node(ctx.node_key0.clone()); v_nodes0.sort(); @@ -1150,19 +1139,40 @@ fn cluster_replace_node_ok() { let mut v_nodes2 = ctx.contract.get_v_nodes_by_node(ctx.node_key2.clone()); v_nodes2.sort(); - assert_eq!(&v_nodes0, &vec![2], "v_nodes must be replaced for the 1st node"); - assert_eq!(&v_nodes1, &vec![4, 5, 6], "v_nodes must not be replaced for the 2nd node"); - assert_eq!(&v_nodes2, &vec![1, 3, 7, 8, 9], "v_nodes must be assigned to the 3rd node"); + assert_eq!( + &v_nodes0, + &vec![2], + "v_nodes must be replaced for the 1st node" + ); + assert_eq!( + &v_nodes1, + &vec![4, 5, 6], + "v_nodes must not be replaced for the 2nd node" + ); + assert_eq!( + &v_nodes2, + &vec![1, 3, 7, 8, 9], + "v_nodes must be assigned to the 3rd node" + ); - let v_nodes0_len : u32 = v_nodes0.len().try_into().unwrap(); - let v_nodes1_len : u32 = v_nodes1.len().try_into().unwrap(); - let v_nodes2_len : u32 = v_nodes2.len().try_into().unwrap(); + let v_nodes0_len: u32 = v_nodes0.len().try_into().unwrap(); + let v_nodes1_len: u32 = v_nodes1.len().try_into().unwrap(); + let v_nodes2_len: u32 = v_nodes2.len().try_into().unwrap(); // Check the changed state of the nodes. let expected_resources = [ - (ctx.node_key0, ctx.node_capacity0 - ctx.resource_per_v_node * v_nodes0_len), - (ctx.node_key1, ctx.node_capacity1 - ctx.resource_per_v_node * v_nodes1_len), - (ctx.node_key2, ctx.node_capacity2 - ctx.resource_per_v_node * v_nodes2_len), + ( + ctx.node_key0, + ctx.node_capacity0 - ctx.resource_per_v_node * v_nodes0_len, + ), + ( + ctx.node_key1, + ctx.node_capacity1 - ctx.resource_per_v_node * v_nodes1_len, + ), + ( + ctx.node_key2, + ctx.node_capacity2 - ctx.resource_per_v_node * v_nodes2_len, + ), ]; for (node_key, available) in expected_resources { @@ -1174,133 +1184,117 @@ fn cluster_replace_node_ok() { } } - #[ink::test] fn cluster_reset_node_err_if_not_cluster_manager() { let mut ctx = setup_cluster(); - let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_manager_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); set_caller_value(not_manager_id, 0); // Reassign a vnode from node1 to node2. assert_eq!( - ctx.contract.cluster_reset_node( - ctx.cluster_id, - ctx.node_key2, - vec![10, 11, 12], - ), + ctx.contract + .cluster_reset_node(ctx.cluster_id, ctx.node_key2, vec![10, 11, 12],), Err(OnlyClusterManager) ); } - #[ink::test] fn cluster_reset_node_err_if_node_does_not_exist() { let mut ctx = setup_cluster(); - let bad_node_key = AccountId::from([0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, 0x9c, 0x76]); + let bad_node_key = AccountId::from([ + 0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, + 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, + 0x9c, 0x76, + ]); set_caller(ctx.manager_id); assert_eq!( - ctx.contract.cluster_reset_node( - ctx.cluster_id, - bad_node_key, - vec![10, 11, 12], - ), + ctx.contract + .cluster_reset_node(ctx.cluster_id, bad_node_key, vec![10, 11, 12],), Err(NodeDoesNotExist) ); } - #[ink::test] fn cluster_reset_node_err_if_no_v_nodes() { let mut ctx = setup_cluster(); assert_eq!( - ctx.contract.cluster_reset_node( - ctx.cluster_id, - ctx.node_key2, - vec![], - ), - Err(AtLeastOneVNodeHasToBeAssigned(ctx.cluster_id, ctx.node_key2)) + ctx.contract + .cluster_reset_node(ctx.cluster_id, ctx.node_key2, vec![],), + Err(AtLeastOneVNodeHasToBeAssigned( + ctx.cluster_id, + ctx.node_key2 + )) ); } - #[ink::test] fn cluster_reset_node_err_if_v_nodes_exceeds_limit() { let mut ctx = setup_cluster(); - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); set_caller_value(ctx.provider_id0, 10); - ctx.contract.node_create( - new_node_key, - NodeParams::from("new_node"), - 1000000000, - 1 - )?; + ctx.contract + .node_create(new_node_key, NodeParams::from("new_node"), 1000000000, 1)?; set_caller_value(ctx.manager_id, 10); - ctx.contract.cluster_add_node( - ctx.cluster_id, - new_node_key, - vec![100], - )?; + ctx.contract + .cluster_add_node(ctx.cluster_id, new_node_key, vec![100])?; let v_nodes: Vec = vec![100; 1801]; assert_eq!( - ctx.contract.cluster_reset_node( - ctx.cluster_id, - new_node_key, - v_nodes, - ), + ctx.contract + .cluster_reset_node(ctx.cluster_id, new_node_key, v_nodes,), Err(VNodesSizeExceedsLimit) ); } - #[ink::test] fn cluster_reset_node_err_if_node_is_not_in_cluster() { let mut ctx = setup_cluster(); - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); set_caller_value(ctx.provider_id0, 10); - ctx.contract.node_create( - new_node_key, - NodeParams::from("new_node"), - 1000000000, - 1 - )?; + ctx.contract + .node_create(new_node_key, NodeParams::from("new_node"), 1000000000, 1)?; set_caller_value(ctx.manager_id, 10); assert_eq!( - ctx.contract.cluster_reset_node( - ctx.cluster_id, - new_node_key, - vec![10, 11, 12], - ), + ctx.contract + .cluster_reset_node(ctx.cluster_id, new_node_key, vec![10, 11, 12],), Err(NodeIsNotAddedToCluster(ctx.cluster_id)) ); } - #[ink::test] fn cluster_reset_node_ok() { let mut ctx = setup_cluster(); set_caller(ctx.manager_id); // Reset vnode for node1 - let new_v_nodes: Vec:: = vec![10, 11, 12]; - ctx.contract.cluster_reset_node( - ctx.cluster_id, - ctx.node_key1, - new_v_nodes.clone(), - )?; + let new_v_nodes: Vec = vec![10, 11, 12]; + ctx.contract + .cluster_reset_node(ctx.cluster_id, ctx.node_key1, new_v_nodes.clone())?; // Check the last event let ev = get_events().pop().unwrap(); assert!(matches!(ev, Event::ClusterNodeReset(ev) if ev == ClusterNodeReset { - cluster_id: ctx.cluster_id, + cluster_id: ctx.cluster_id, node_key: ctx.node_key1, v_nodes: new_v_nodes } @@ -1314,7 +1308,10 @@ fn cluster_reset_node_ok() { let mut cluster_info = ctx.contract.cluster_get(ctx.cluster_id)?; cluster_info.cluster_v_nodes.sort(); - assert_eq!(&cluster_info.cluster_v_nodes, &cluster_v_nodes, "a v_node must be replaced"); + assert_eq!( + &cluster_info.cluster_v_nodes, &cluster_v_nodes, + "a v_node must be replaced" + ); let mut v_nodes0 = ctx.contract.get_v_nodes_by_node(ctx.node_key0.clone()); v_nodes0.sort(); @@ -1323,13 +1320,23 @@ fn cluster_reset_node_ok() { let mut v_nodes2 = ctx.contract.get_v_nodes_by_node(ctx.node_key2.clone()); v_nodes2.sort(); - assert_eq!(&v_nodes0, &vec![1, 2, 3], "v_nodes must not be reset for the 1st node"); - assert_eq!(&v_nodes1, &vec![10, 11, 12], "v_nodes must not be reset for the 2nd node"); - assert_eq!(&v_nodes2, &vec![7, 8, 9], "v_nodes must not be reset to the 3rd node"); - + assert_eq!( + &v_nodes0, + &vec![1, 2, 3], + "v_nodes must not be reset for the 1st node" + ); + assert_eq!( + &v_nodes1, + &vec![10, 11, 12], + "v_nodes must not be reset for the 2nd node" + ); + assert_eq!( + &v_nodes2, + &vec![7, 8, 9], + "v_nodes must not be reset to the 3rd node" + ); } - #[ink::test] fn cluster_reserve_resource_ok() { let mut ctx = setup_cluster(); @@ -1338,13 +1345,14 @@ fn cluster_reserve_resource_ok() { let new_resource_per_v_node = 15; // Reserve more resources. - ctx.contract.cluster_set_resource_per_v_node(ctx.cluster_id, new_resource_per_v_node)?; + ctx.contract + .cluster_set_resource_per_v_node(ctx.cluster_id, new_resource_per_v_node)?; // Check the last event. let ev = get_events().pop().unwrap(); assert!(matches!(ev, Event::ClusterReserveResource(ev) if ev == - ClusterReserveResource { - cluster_id: ctx.cluster_id, + ClusterReserveResource { + cluster_id: ctx.cluster_id, resource: new_resource_per_v_node } )); @@ -1353,15 +1361,24 @@ fn cluster_reserve_resource_ok() { let cluster = ctx.contract.cluster_get(ctx.cluster_id)?.cluster; assert_eq!(cluster.resource_per_v_node, new_resource_per_v_node); - let v_nodes0_len : u32 = ctx.v_nodes0.len().try_into().unwrap(); - let v_nodes1_len : u32 = ctx.v_nodes1.len().try_into().unwrap(); - let v_nodes2_len : u32 = ctx.v_nodes2.len().try_into().unwrap(); + let v_nodes0_len: u32 = ctx.v_nodes0.len().try_into().unwrap(); + let v_nodes1_len: u32 = ctx.v_nodes1.len().try_into().unwrap(); + let v_nodes2_len: u32 = ctx.v_nodes2.len().try_into().unwrap(); // Check the changed state of the nodes. let expected_resources = [ - (ctx.node_key0, ctx.node_capacity0 - new_resource_per_v_node * v_nodes0_len), - (ctx.node_key1, ctx.node_capacity1 - new_resource_per_v_node * v_nodes1_len), - (ctx.node_key2, ctx.node_capacity2 - new_resource_per_v_node * v_nodes2_len), + ( + ctx.node_key0, + ctx.node_capacity0 - new_resource_per_v_node * v_nodes0_len, + ), + ( + ctx.node_key1, + ctx.node_capacity1 - new_resource_per_v_node * v_nodes1_len, + ), + ( + ctx.node_key2, + ctx.node_capacity2 - new_resource_per_v_node * v_nodes2_len, + ), ]; for (node_id, available) in expected_resources { assert_eq!( @@ -1372,7 +1389,6 @@ fn cluster_reserve_resource_ok() { } } - #[ink::test] fn cluster_distribute_revenue_ok() { let ctx = &mut setup_cluster(); @@ -1402,11 +1418,12 @@ fn cluster_distribute_revenue_ok() { let network_fee_bp = 100; // 1% let cluster_management_fee_bp = 200; // 2% set_caller_value(admin_id(), CONTRACT_FEE_LIMIT); - ctx.contract.admin_set_network_fee_config(NetworkFeeConfig { - network_fee_bp, - network_fee_destination: AccountId::default(), - cluster_management_fee_bp, - })?; + ctx.contract + .admin_set_network_fee_config(NetworkFeeConfig { + network_fee_bp, + network_fee_destination: AccountId::default(), + cluster_management_fee_bp, + })?; let burned_fee = to_distribute * network_fee_bp / BASIS_POINTS; let manager_fee = (to_distribute - burned_fee) * cluster_management_fee_bp / BASIS_POINTS; @@ -1424,9 +1441,9 @@ fn cluster_distribute_revenue_ok() { for provider_id in expected_recipients { assert!( matches!(events.pop().unwrap(), Event::ClusterDistributeRevenues(ev) if ev == - ClusterDistributeRevenues { - cluster_id: ctx.cluster_id, - provider_id + ClusterDistributeRevenues { + cluster_id: ctx.cluster_id, + provider_id }) ); } @@ -1479,12 +1496,15 @@ fn cluster_distribute_revenue_ok() { ); } - #[ink::test] fn cluster_remove_err_if_not_cluster_manager() { let mut ctx = setup_cluster(); - let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_manager_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); set_balance(not_manager_id, 1000 * TOKEN); set_caller(not_manager_id); @@ -1494,7 +1514,6 @@ fn cluster_remove_err_if_not_cluster_manager() { ); } - #[ink::test] fn cluster_remove_err_if_cluster_is_not_empty() { let mut ctx = setup_cluster(); @@ -1506,42 +1525,29 @@ fn cluster_remove_err_if_cluster_is_not_empty() { ); } - #[ink::test] fn cluster_remove_ok() { let mut ctx = setup_cluster(); set_caller(ctx.manager_id); - ctx.contract.cluster_remove_node( - ctx.cluster_id, - ctx.node_key0, - )?; + ctx.contract + .cluster_remove_node(ctx.cluster_id, ctx.node_key0)?; - ctx.contract.cluster_remove_node( - ctx.cluster_id, - ctx.node_key1, - )?; + ctx.contract + .cluster_remove_node(ctx.cluster_id, ctx.node_key1)?; - ctx.contract.cluster_remove_node( - ctx.cluster_id, - ctx.node_key2, - )?; + ctx.contract + .cluster_remove_node(ctx.cluster_id, ctx.node_key2)?; - ctx.contract.cluster_remove_cdn_node( - ctx.cluster_id, - ctx.cdn_node_key0, - )?; + ctx.contract + .cluster_remove_cdn_node(ctx.cluster_id, ctx.cdn_node_key0)?; - ctx.contract.cluster_remove_cdn_node( - ctx.cluster_id, - ctx.cdn_node_key1, - )?; + ctx.contract + .cluster_remove_cdn_node(ctx.cluster_id, ctx.cdn_node_key1)?; - ctx.contract.cluster_remove_cdn_node( - ctx.cluster_id, - ctx.cdn_node_key2, - )?; + ctx.contract + .cluster_remove_cdn_node(ctx.cluster_id, ctx.cdn_node_key2)?; ctx.contract.cluster_remove(ctx.cluster_id)?; @@ -1556,15 +1562,17 @@ fn cluster_remove_ok() { ctx.contract.cluster_get(ctx.cluster_id), Err(ClusterDoesNotExist) ); - } - #[ink::test] fn cluster_set_node_status_err_if_not_cluster_manager() { let mut ctx = setup_cluster(); - let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_manager_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); set_balance(not_manager_id, 1000 * TOKEN); set_caller(not_manager_id); @@ -1578,7 +1586,6 @@ fn cluster_set_node_status_err_if_not_cluster_manager() { ); } - #[ink::test] fn cluster_set_node_status_ok() { let mut ctx = setup_cluster(); @@ -1587,7 +1594,7 @@ fn cluster_set_node_status_ok() { ctx.contract.cluster_set_node_status( ctx.cluster_id, ctx.node_key0, - NodeStatusInCluster::ACTIVE + NodeStatusInCluster::ACTIVE, )?; let node_info = ctx.contract.node_get(ctx.node_key0)?; @@ -1597,12 +1604,15 @@ fn cluster_set_node_status_ok() { ); } - #[ink::test] fn cluster_set_cdn_node_status_err_if_not_cluster_manager() { let mut ctx = setup_cluster(); - let not_manager_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_manager_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); set_balance(not_manager_id, 1000 * TOKEN); set_caller(not_manager_id); @@ -1616,7 +1626,6 @@ fn cluster_set_cdn_node_status_err_if_not_cluster_manager() { ); } - #[ink::test] fn cluster_set_cdn_node_status_ok() { let mut ctx = setup_cluster(); @@ -1625,7 +1634,7 @@ fn cluster_set_cdn_node_status_ok() { ctx.contract.cluster_set_cdn_node_status( ctx.cluster_id, ctx.cdn_node_key0, - NodeStatusInCluster::ACTIVE + NodeStatusInCluster::ACTIVE, )?; let cdn_node_info = ctx.contract.cdn_node_get(ctx.cdn_node_key0)?; @@ -1635,7 +1644,6 @@ fn cluster_set_cdn_node_status_ok() { ); } - #[ink::test] fn cluster_get_err_if_cluster_does_not_exist() { let ctx = setup_cluster(); @@ -1647,7 +1655,6 @@ fn cluster_get_err_if_cluster_does_not_exist() { ); } - #[ink::test] fn cluster_get_ok() { let ctx = setup_cluster(); @@ -1657,8 +1664,7 @@ fn cluster_get_ok() { cluster_v_nodes1.extend(ctx.v_nodes1.clone()); cluster_v_nodes1.extend(ctx.v_nodes2.clone()); - let total_rent = - ctx.rent_v_node_per_month0 * ctx.v_nodes0.len() as Balance + let total_rent = ctx.rent_v_node_per_month0 * ctx.v_nodes0.len() as Balance + ctx.rent_v_node_per_month1 * ctx.v_nodes1.len() as Balance + ctx.rent_v_node_per_month2 * ctx.v_nodes2.len() as Balance; @@ -1679,13 +1685,12 @@ fn cluster_get_ok() { cdn_usd_per_gb: CDN_USD_PER_GB, cdn_revenues: Cash(0), }, - cluster_v_nodes: cluster_v_nodes1 + cluster_v_nodes: cluster_v_nodes1, } }) ); } - #[ink::test] fn cluster_list_ok() { let mut ctx = setup_cluster(); @@ -1695,8 +1700,7 @@ fn cluster_list_ok() { cluster_v_nodes1.extend(ctx.v_nodes1.clone()); cluster_v_nodes1.extend(ctx.v_nodes2.clone()); - let total_rent = - ctx.rent_v_node_per_month0 * ctx.v_nodes0.len() as Balance + let total_rent = ctx.rent_v_node_per_month0 * ctx.v_nodes0.len() as Balance + ctx.rent_v_node_per_month1 * ctx.v_nodes1.len() as Balance + ctx.rent_v_node_per_month2 * ctx.v_nodes2.len() as Balance; @@ -1714,20 +1718,23 @@ fn cluster_list_ok() { cdn_usd_per_gb: CDN_USD_PER_GB, cdn_revenues: Cash(0), }, - cluster_v_nodes: cluster_v_nodes1 + cluster_v_nodes: cluster_v_nodes1, }; let cluster_params2 = ClusterParams::from("{}"); let resource_per_v_node2 = 10; - let manager_id2 = AccountId::from([0x82, 0x61, 0x19, 0xd5, 0xcf, 0x47, 0xdc, 0xb9, 0xc6, 0xff, 0x1a, 0x3e, 0x46, 0x03, 0x6d, 0xad, 0x1f, 0xea, 0x66, 0x18, 0x96, 0x2e, 0x4a, 0x5e, 0x89, 0xe0, 0x96, 0x74, 0xcf, 0x80, 0xf1, 0x30]); + let manager_id2 = AccountId::from([ + 0x82, 0x61, 0x19, 0xd5, 0xcf, 0x47, 0xdc, 0xb9, 0xc6, 0xff, 0x1a, 0x3e, 0x46, 0x03, 0x6d, + 0xad, 0x1f, 0xea, 0x66, 0x18, 0x96, 0x2e, 0x4a, 0x5e, 0x89, 0xe0, 0x96, 0x74, 0xcf, 0x80, + 0xf1, 0x30, + ]); set_balance(manager_id2, 1000 * TOKEN); set_caller(manager_id2); - let cluster_id2 = ctx.contract.cluster_create( - cluster_params2.clone(), - resource_per_v_node2 - )?; + let cluster_id2 = ctx + .contract + .cluster_create(cluster_params2.clone(), resource_per_v_node2)?; let cluster2 = ClusterInfo { cluster_id: cluster_id2, @@ -1743,12 +1750,11 @@ fn cluster_list_ok() { cdn_usd_per_gb: CDN_USD_PER_GB, cdn_revenues: Cash(0), }, - cluster_v_nodes: Vec::new() + cluster_v_nodes: Vec::new(), }; let count = 2; - assert_eq!( ctx.contract.cluster_list(0, 100, None), (vec![cluster1.clone(), cluster2.clone()], count) @@ -1769,7 +1775,6 @@ fn cluster_list_ok() { (vec![cluster2.clone()], count) ); - assert_eq!(ctx.contract.cluster_list(21, 20, None), (vec![], count)); // Filter by manager. @@ -1783,22 +1788,33 @@ fn cluster_list_ok() { (vec![cluster2.clone()], count) ); - let not_manager_id= AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_manager_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); assert_eq!( ctx.contract.cluster_list(0, 100, Some(not_manager_id)), (vec![], count) ); } - #[ink::test] fn grant_and_revoke_trusted_manager_permission_ok() { let mut contract = setup_contract(); - let grantor = AccountId::from([0x92, 0xad, 0x47, 0xdf, 0xb9, 0x6b, 0x2b, 0x4a, 0xd5, 0xb0, 0xe3, 0x6d, 0x56, 0x33, 0x27, 0xfd, 0xcf, 0x9d, 0xee, 0x06, 0xf4, 0x0d, 0x41, 0x48, 0xe1, 0x6a, 0x5c, 0xaa, 0x6c, 0x0d, 0x17, 0x4b]); + let grantor = AccountId::from([ + 0x92, 0xad, 0x47, 0xdf, 0xb9, 0x6b, 0x2b, 0x4a, 0xd5, 0xb0, 0xe3, 0x6d, 0x56, 0x33, 0x27, + 0xfd, 0xcf, 0x9d, 0xee, 0x06, 0xf4, 0x0d, 0x41, 0x48, 0xe1, 0x6a, 0x5c, 0xaa, 0x6c, 0x0d, + 0x17, 0x4b, + ]); set_balance(grantor, 1000 * TOKEN); - let grantee = AccountId::from([0x1a, 0xa6, 0x69, 0xb4, 0x23, 0xe4, 0x8b, 0xbd, 0xc4, 0x65, 0xe3, 0xee, 0x17, 0xfd, 0x5b, 0x6d, 0x6f, 0xae, 0x6f, 0xf1, 0x40, 0x52, 0x03, 0x65, 0x02, 0xe4, 0x50, 0xb5, 0x0b, 0x34, 0xe2, 0x7a]); + let grantee = AccountId::from([ + 0x1a, 0xa6, 0x69, 0xb4, 0x23, 0xe4, 0x8b, 0xbd, 0xc4, 0x65, 0xe3, 0xee, 0x17, 0xfd, 0x5b, + 0x6d, 0x6f, 0xae, 0x6f, 0xf1, 0x40, 0x52, 0x03, 0x65, 0x02, 0xe4, 0x50, 0xb5, 0x0b, 0x34, + 0xe2, 0x7a, + ]); set_balance(grantee, 1000 * TOKEN); let permission = Permission::ClusterManagerTrustedBy(grantor); @@ -1830,10 +1846,8 @@ fn grant_and_revoke_trusted_manager_permission_ok() { permission }) ); - } - #[ink::test] fn cluster_distribute_cdn_revenue_ok() { // todo: this test scenario must be revised as it does pure printing without any assertion @@ -1876,7 +1890,8 @@ fn cluster_distribute_cdn_revenue_ok() { let permission = Permission::Validator; set_caller(admin_id()); - ctx.contract.admin_grant_permission(admin_id(), permission)?; + ctx.contract + .admin_grant_permission(admin_id(), permission)?; ctx.contract.cluster_put_cdn_revenue( ctx.cluster_id, @@ -1912,7 +1927,8 @@ fn cluster_distribute_cdn_revenue_ok() { set_caller(ctx.provider_id0); - ctx.contract.cluster_distribute_cdn_revenue(ctx.cluster_id)?; + ctx.contract + .cluster_distribute_cdn_revenue(ctx.cluster_id)?; let cdn_node0 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key0).unwrap(); let cdn_node1 = ctx.contract.cdn_nodes.get(ctx.cdn_node_key1).unwrap(); @@ -1924,5 +1940,4 @@ fn cluster_distribute_cdn_revenue_ok() { let account0_after_distributing = ctx.contract.accounts.get(&ctx.provider_id0).unwrap(); println!("{:?}", account0_after_distributing); - } diff --git a/bucket/ddc_bucket/tests/test_currency.rs b/bucket/ddc_bucket/tests/test_currency.rs index 2d1e86be..a541a78c 100644 --- a/bucket/ddc_bucket/tests/test_currency.rs +++ b/bucket/ddc_bucket/tests/test_currency.rs @@ -1,9 +1,8 @@ use ink_lang as ink; -use crate::ddc_bucket::*; use super::env_utils::*; use super::setup_utils::*; - +use crate::ddc_bucket::*; #[ink::test] fn currency_conversion_init_ok() { @@ -17,7 +16,6 @@ fn currency_conversion_init_ok() { ); } - #[ink::test] fn currency_conversion_set_rate_ok() { let mut contract = setup_contract(); @@ -34,7 +32,6 @@ fn currency_conversion_set_rate_ok() { ); } - #[ink::test] #[should_panic] fn currency_conversion_set_rate_err_if_not_admin() { @@ -45,7 +42,6 @@ fn currency_conversion_set_rate_err_if_not_admin() { contract.account_set_usd_per_cere(9)?; } - #[ink::test] fn converter_ok() { // todo: this test scenario must be revised as it does pure printing without any assertion diff --git a/bucket/ddc_bucket/tests/test_node.rs b/bucket/ddc_bucket/tests/test_node.rs index f1effe2d..4e7ec42e 100644 --- a/bucket/ddc_bucket/tests/test_node.rs +++ b/bucket/ddc_bucket/tests/test_node.rs @@ -1,10 +1,9 @@ use ink_lang as ink; -use crate::ddc_bucket::Error::*; -use crate::ddc_bucket::*; use super::env_utils::*; use super::setup_utils::*; - +use crate::ddc_bucket::Error::*; +use crate::ddc_bucket::*; #[ink::test] fn node_create_err_if_node_exists() { @@ -20,15 +19,22 @@ fn node_create_err_if_node_exists() { ); } - #[ink::test] fn node_create_ok() { let mut ctx = setup_cluster(); - let new_provider_id = AccountId::from([0x76, 0x30, 0xc6, 0x96, 0x6f, 0xd3, 0x26, 0xba, 0x1a, 0xa0, 0x6f, 0xd8, 0x7f, 0x7b, 0xf2, 0xef, 0x14, 0x11, 0xf0, 0x0d, 0x00, 0xa9, 0xe7, 0x11, 0xdf, 0xd1, 0x65, 0x14, 0x5d, 0x01, 0xdb, 0x59]); + let new_provider_id = AccountId::from([ + 0x76, 0x30, 0xc6, 0x96, 0x6f, 0xd3, 0x26, 0xba, 0x1a, 0xa0, 0x6f, 0xd8, 0x7f, 0x7b, 0xf2, + 0xef, 0x14, 0x11, 0xf0, 0x0d, 0x00, 0xa9, 0xe7, 0x11, 0xdf, 0xd1, 0x65, 0x14, 0x5d, 0x01, + 0xdb, 0x59, + ]); set_balance(new_provider_id, 1000 * TOKEN); - let new_node_key = AccountId::from([0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, 0x84, 0x31]); + let new_node_key = AccountId::from([ + 0xc4, 0xcd, 0xaa, 0xfa, 0xf1, 0x30, 0x7d, 0x23, 0xf4, 0x99, 0x84, 0x71, 0xdf, 0x78, 0x59, + 0xce, 0x06, 0x3d, 0xce, 0x78, 0x59, 0xc4, 0x3a, 0xe8, 0xef, 0x12, 0x0a, 0xbc, 0x43, 0xc4, + 0x84, 0x31, + ]); let new_node_params = NodeParams::from("{\"url\":\"https://ddc-1.cere.network/storage/new\"}"); let new_node_capacity = 100; let new_node_rent_v_node_per_month: Balance = 10 * TOKEN; @@ -43,12 +49,12 @@ fn node_create_ok() { assert!( matches!(get_events().pop().unwrap(), Event::NodeCreated(ev) if ev == - NodeCreated { - node_key: new_node_key, - provider_id: new_provider_id, - rent_v_node_per_month: new_node_rent_v_node_per_month, - node_params: new_node_params.clone() - }) + NodeCreated { + node_key: new_node_key, + provider_id: new_provider_id, + rent_v_node_per_month: new_node_rent_v_node_per_month, + node_params: new_node_params.clone() + }) ); let node_info = ctx.contract.node_get(new_node_key)?; @@ -61,15 +67,17 @@ fn node_create_ok() { status_in_cluster: None, }; assert!(matches!(node_info.node, _expected_node_info)); - } - #[ink::test] fn node_remove_err_if_not_provider() { let mut ctx = setup_cluster(); - let not_provider_id = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_provider_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); set_balance(not_provider_id, 1000 * TOKEN); set_caller(not_provider_id); @@ -79,7 +87,6 @@ fn node_remove_err_if_not_provider() { ); } - #[ink::test] fn node_remove_err_if_node_in_cluster() { let mut ctx = setup_cluster(); @@ -91,13 +98,13 @@ fn node_remove_err_if_node_in_cluster() { ); } - #[ink::test] fn node_remove_ok() { let mut ctx = setup_cluster(); set_caller(ctx.provider_id1); - ctx.contract.cluster_remove_node(ctx.cluster_id, ctx.node_key1)?; + ctx.contract + .cluster_remove_node(ctx.cluster_id, ctx.node_key1)?; ctx.contract.node_remove(ctx.node_key1)?; assert!( @@ -108,33 +115,29 @@ fn node_remove_ok() { ) ); - assert_eq!( - ctx.contract.node_get(ctx.node_key1), - Err(NodeDoesNotExist) - ); + assert_eq!(ctx.contract.node_get(ctx.node_key1), Err(NodeDoesNotExist)); } - #[ink::test] fn node_set_params_err_if_not_provider() { let mut ctx = setup_cluster(); - let not_provider = AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_provider = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); set_balance(not_provider, 1000 * TOKEN); // Change params.not_provider let new_node_params = NodeParams::from("new node params"); set_caller_value(not_provider, CONTRACT_FEE_LIMIT); assert_eq!( - ctx.contract.node_set_params( - ctx.node_key0, - new_node_params - ), + ctx.contract.node_set_params(ctx.node_key0, new_node_params), Err(OnlyNodeProvider) ); } - #[ink::test] fn node_set_params_ok() { let mut ctx = setup_cluster(); @@ -142,7 +145,8 @@ fn node_set_params_ok() { // Change params. let new_node_params = NodeParams::from("new node params"); set_caller_value(ctx.provider_id0, CONTRACT_FEE_LIMIT); - ctx.contract.node_set_params(ctx.node_key0, new_node_params.clone())?; + ctx.contract + .node_set_params(ctx.node_key0, new_node_params.clone())?; assert!( matches!(get_events().pop().unwrap(), Event::NodeParamsSet(ev) if ev == @@ -158,30 +162,29 @@ fn node_set_params_ok() { assert_eq!(node_info.node.node_params, new_node_params); } - #[ink::test] fn node_get_err_if_node_does_not_exist() { let ctx = setup_cluster(); - let bad_node_key = AccountId::from([0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, 0x9c, 0x76]); + let bad_node_key = AccountId::from([ + 0xf6, 0x8f, 0x06, 0xa8, 0x26, 0xba, 0xaf, 0x7f, 0xbd, 0x9b, 0xff, 0x3d, 0x1e, 0xec, 0xae, + 0xef, 0xc7, 0x7a, 0x01, 0x6d, 0x0b, 0xaf, 0x4c, 0x90, 0x55, 0x6e, 0x7b, 0x15, 0x73, 0x46, + 0x9c, 0x76, + ]); - assert_eq!( - ctx.contract.node_get(bad_node_key), - Err(NodeDoesNotExist) - ); + assert_eq!(ctx.contract.node_get(bad_node_key), Err(NodeDoesNotExist)); } - #[ink::test] fn node_get_ok() { let ctx = setup_cluster(); - let v_nodes1_len : u32 = ctx.v_nodes1.len().try_into().unwrap(); + let v_nodes1_len: u32 = ctx.v_nodes1.len().try_into().unwrap(); assert_eq!( ctx.contract.node_get(ctx.node_key1), Ok({ - NodeInfo { - node_key: ctx.node_key1, + NodeInfo { + node_key: ctx.node_key1, node: Node { provider_id: ctx.provider_id1, rent_v_node_per_month: ctx.rent_v_node_per_month1, @@ -189,14 +192,13 @@ fn node_get_ok() { node_params: ctx.node_params1, cluster_id: Some(ctx.cluster_id), status_in_cluster: Some(NodeStatusInCluster::ADDING), - }, - v_nodes: ctx.v_nodes1 + }, + v_nodes: ctx.v_nodes1, } }) ); } - #[ink::test] fn node_list_ok() { let ctx = setup_cluster(); @@ -204,7 +206,7 @@ fn node_list_ok() { let node_info = ctx.contract.node_get(ctx.node_key1)?; assert_eq!(ctx.provider_id1, node_info.node.provider_id.clone()); - let v_nodes1_len : u32 = ctx.v_nodes1.len().try_into().unwrap(); + let v_nodes1_len: u32 = ctx.v_nodes1.len().try_into().unwrap(); let node1 = NodeInfo { node_key: ctx.node_key1, node: Node { @@ -215,21 +217,21 @@ fn node_list_ok() { status_in_cluster: Some(NodeStatusInCluster::ADDING), node_params: ctx.node_params1, }, - v_nodes: ctx.v_nodes1.clone() + v_nodes: ctx.v_nodes1.clone(), }; - let v_nodes2_len : u32 = ctx.v_nodes2.len().try_into().unwrap(); + let v_nodes2_len: u32 = ctx.v_nodes2.len().try_into().unwrap(); let node2 = NodeInfo { node_key: ctx.node_key2, node: Node { - provider_id:ctx.provider_id2, + provider_id: ctx.provider_id2, rent_v_node_per_month: ctx.rent_v_node_per_month2, free_resource: ctx.node_capacity2 - ctx.resource_per_v_node * v_nodes2_len, cluster_id: Some(ctx.cluster_id), status_in_cluster: Some(NodeStatusInCluster::ADDING), node_params: ctx.node_params2, }, - v_nodes: ctx.v_nodes2.clone() + v_nodes: ctx.v_nodes2.clone(), }; let count = 3; @@ -267,7 +269,11 @@ fn node_list_ok() { (vec![node2.clone()], count) ); - let not_provider_id= AccountId::from([0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, 0xf8, 0x6d]); + let not_provider_id = AccountId::from([ + 0xee, 0x0a, 0xc9, 0x58, 0xa2, 0x0d, 0xe8, 0xda, 0x73, 0xb2, 0x05, 0xe9, 0xc6, 0x34, 0xa6, + 0xb2, 0x23, 0xcc, 0x54, 0x30, 0x24, 0x5d, 0x89, 0xb6, 0x4d, 0x83, 0x9b, 0x6d, 0xca, 0xc4, + 0xf8, 0x6d, + ]); assert_eq!( ctx.contract.node_list(1, 100, Some(not_provider_id)), diff --git a/bucket/ddc_bucket/topology/messages.rs b/bucket/ddc_bucket/topology/messages.rs index 51051404..40f6f902 100644 --- a/bucket/ddc_bucket/topology/messages.rs +++ b/bucket/ddc_bucket/topology/messages.rs @@ -1,11 +1,9 @@ //! The public interface to manage Nodes. -use crate::ddc_bucket::{NodeKey, ClusterId, VNodeToken, DdcBucket, Result}; +use crate::ddc_bucket::{ClusterId, DdcBucket, NodeKey, Result, VNodeToken}; use ink_prelude::vec::Vec; - impl DdcBucket { - pub fn message_get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Vec { self.topology.get_v_nodes_by_cluster(cluster_id) } @@ -14,8 +12,11 @@ impl DdcBucket { self.topology.get_v_nodes_by_node(node_key) } - pub fn message_get_node_by_v_node(&self, cluster_id: ClusterId, v_node: VNodeToken) -> Result { + pub fn message_get_node_by_v_node( + &self, + cluster_id: ClusterId, + v_node: VNodeToken, + ) -> Result { self.topology.get_node_by_v_node(cluster_id, v_node) } - -} \ No newline at end of file +} diff --git a/bucket/ddc_bucket/topology/mod.rs b/bucket/ddc_bucket/topology/mod.rs index 61483b4e..b05b5b88 100644 --- a/bucket/ddc_bucket/topology/mod.rs +++ b/bucket/ddc_bucket/topology/mod.rs @@ -1,4 +1,4 @@ //! cluster topology management. -pub mod store; pub mod messages; +pub mod store; diff --git a/bucket/ddc_bucket/topology/store.rs b/bucket/ddc_bucket/topology/store.rs index ba8d2a8a..4edc5e7d 100644 --- a/bucket/ddc_bucket/topology/store.rs +++ b/bucket/ddc_bucket/topology/store.rs @@ -1,10 +1,10 @@ //! The store where to create and access Nodes. use ink_prelude::vec::Vec; -use ink_storage::Mapping; use ink_storage::traits::{SpreadAllocate, SpreadLayout}; +use ink_storage::Mapping; use crate::ddc_bucket::cluster::entity::ClusterId; -use crate::ddc_bucket::node::entity::{NodeKey}; +use crate::ddc_bucket::node::entity::NodeKey; use crate::ddc_bucket::{Error::*, Result}; pub type VNodeToken = u64; @@ -26,9 +26,10 @@ pub struct TopologyStore { } impl TopologyStore { - pub fn get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Vec { - self.cluster_v_nodes_map.get(cluster_id).unwrap_or(Vec::new()) + self.cluster_v_nodes_map + .get(cluster_id) + .unwrap_or(Vec::new()) } pub fn get_v_nodes_by_node(&self, node_key: NodeKey) -> Vec { @@ -36,22 +37,22 @@ impl TopologyStore { } pub fn get_node_by_v_node(&self, cluster_id: ClusterId, v_node: VNodeToken) -> Result { - self.nodes_map.get((cluster_id, v_node)).ok_or(VNodeIsNotAssignedToNode(cluster_id, v_node)) + self.nodes_map + .get((cluster_id, v_node)) + .ok_or(VNodeIsNotAssignedToNode(cluster_id, v_node)) } pub fn v_node_has_node(&self, cluster_id: ClusterId, v_node: VNodeToken) -> bool { self.nodes_map.contains((cluster_id, v_node)) } - pub fn create_topology( - &mut self, - cluster_id: ClusterId, - ) -> Result<()> { + pub fn create_topology(&mut self, cluster_id: ClusterId) -> Result<()> { if self.cluster_v_nodes_map.contains(&cluster_id) { Err(TopologyAlreadyExists) } else { let cluster_v_nodes: Vec = Vec::new(); - self.cluster_v_nodes_map.insert(cluster_id, &cluster_v_nodes); + self.cluster_v_nodes_map + .insert(cluster_id, &cluster_v_nodes); Ok(()) } } @@ -62,7 +63,6 @@ impl TopologyStore { node_key: NodeKey, v_nodes: Vec, ) -> Result<()> { - if v_nodes.is_empty() { return Err(AtLeastOneVNodeHasToBeAssigned(cluster_id, node_key)); } @@ -78,7 +78,6 @@ impl TopologyStore { } for v_node in &v_nodes { - // vnode that is being added should not exist in the cluster topology if self.v_node_has_node(cluster_id, *v_node) { return Err(VNodeIsAlreadyAssignedToNode(node_key)); @@ -91,31 +90,25 @@ impl TopologyStore { cluster_v_nodes.push(*v_node); } - self.cluster_v_nodes_map.insert(cluster_id, &cluster_v_nodes); - + self.cluster_v_nodes_map + .insert(cluster_id, &cluster_v_nodes); + // vnodes that are being added should be assigned to the physical node self.v_nodes_map.insert(node_key, &v_nodes); Ok(()) } - - pub fn remove_node( - &mut self, - cluster_id: ClusterId, - node_key: NodeKey - ) -> Result<()> { - + pub fn remove_node(&mut self, cluster_id: ClusterId, node_key: NodeKey) -> Result<()> { let mut cluster_v_nodes = self.get_v_nodes_by_cluster(cluster_id); let v_nodes = self.get_v_nodes_by_node(node_key); for v_node in &v_nodes { - // vnode that is being removed should exist in the cluster topology if !self.v_node_has_node(cluster_id, *v_node) { return Err(VNodeIsNotAssignedToNode(cluster_id, *v_node)); } - + // vnode that is being removed should be unusigned from the physical node self.nodes_map.remove((cluster_id, v_node)); @@ -125,15 +118,14 @@ impl TopologyStore { }; } - self.cluster_v_nodes_map.insert(cluster_id, &cluster_v_nodes); + self.cluster_v_nodes_map + .insert(cluster_id, &cluster_v_nodes); // vnodes that are being removed should be unusigned from the physical node self.v_nodes_map.remove(node_key); Ok(()) - } - pub fn replace_node( &mut self, @@ -141,7 +133,6 @@ impl TopologyStore { new_node_key: NodeKey, v_nodes_to_reasign: Vec, ) -> Result<()> { - if v_nodes_to_reasign.is_empty() { return Err(AtLeastOneVNodeHasToBeAssigned(cluster_id, new_node_key)); } @@ -153,12 +144,11 @@ impl TopologyStore { let cluster_v_nodes = self.get_v_nodes_by_cluster(cluster_id); for v_node in &v_nodes_to_reasign { - // vnode that is being reasigned should be in the cluster topology if None == cluster_v_nodes.iter().position(|x| *x == *v_node) { return Err(VNodeDoesNotExistsInCluster(cluster_id)); }; - + // vnode that is being reasigned should be already assigned to a physical node let old_node_key = self.get_node_by_v_node(cluster_id, *v_node)?; @@ -175,7 +165,7 @@ impl TopologyStore { } self.v_nodes_map.insert(old_node_key, &old_node_v_nodes); - + // vnode that is being reasigned should be assined to the new physical node self.nodes_map.insert(&(cluster_id, *v_node), &new_node_key); } @@ -193,36 +183,27 @@ impl TopologyStore { Ok(()) } - pub fn reset_node( &mut self, cluster_id: ClusterId, node_key: NodeKey, new_v_nodes: Vec, ) -> Result<()> { - self.remove_node(cluster_id, node_key)?; self.add_node(cluster_id, node_key, new_v_nodes) - } - pub fn remove_topology( - &mut self, - cluster_id: ClusterId, - ) -> Result<()> { - + pub fn remove_topology(&mut self, cluster_id: ClusterId) -> Result<()> { let cluster_v_nodes: Vec = self.get_v_nodes_by_cluster(cluster_id); for v_node in &cluster_v_nodes { let node_key = self.get_node_by_v_node(cluster_id, *v_node)?; self.nodes_map.remove((cluster_id, v_node)); - self.v_nodes_map.remove(node_key); + self.v_nodes_map.remove(node_key); } self.cluster_v_nodes_map.remove(cluster_id); Ok(()) } - - } diff --git a/bucket/lib.rs b/bucket/lib.rs index 7f34bdac..f6463639 100755 --- a/bucket/lib.rs +++ b/bucket/lib.rs @@ -24,9 +24,9 @@ pub mod ddc_bucket { use crate::ddc_bucket::cdn_node::store::CdnNodeStore; use crate::ddc_bucket::perm::entity::Permission; - use self::cdn_node::entity::{CdnNodeInfo, CdnNodeKey, CdnNodeParams}; use self::account::entity::Account; - use self::protocol::store::{ProtocolStore, NetworkFeeConfig}; + use self::cdn_node::entity::{CdnNodeInfo, CdnNodeKey, CdnNodeParams}; + use self::protocol::store::{NetworkFeeConfig, ProtocolStore}; use self::topology::store::TopologyStore; pub mod account; @@ -68,14 +68,16 @@ pub mod ddc_bucket { pub fn new() -> Self { ink_lang::utils::initialize_contract(|contract: &mut Self| { let admin = Self::env().caller(); - contract.perms.grant_permission(admin, Permission::SuperAdmin); + contract + .perms + .grant_permission(admin, Permission::SuperAdmin); contract.committer.init(admin); contract.protocol.init( - DEFAULT_PROTOCOL_FEE_BP, + DEFAULT_PROTOCOL_FEE_BP, admin, DEFAULT_NETWORK_FEE_BP, admin, - DEFAULT_CLUSTER_FEE_BP + DEFAULT_CLUSTER_FEE_BP, ); }) } @@ -155,7 +157,11 @@ pub mod ddc_bucket { /// /// Provide the account of new owner #[ink(message, payable)] - pub fn bucket_change_owner(&mut self, bucket_id: BucketId, owner_id: AccountId) -> Result<()> { + pub fn bucket_change_owner( + &mut self, + bucket_id: BucketId, + owner_id: AccountId, + ) -> Result<()> { self.message_bucket_change_owner(bucket_id, owner_id) } @@ -163,7 +169,11 @@ pub mod ddc_bucket { /// /// The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes). #[ink(message)] - pub fn bucket_alloc_into_cluster(&mut self, bucket_id: BucketId, resource: Resource) -> Result<()> { + pub fn bucket_alloc_into_cluster( + &mut self, + bucket_id: BucketId, + resource: Resource, + ) -> Result<()> { self.message_bucket_alloc_into_cluster(bucket_id, resource) } @@ -177,7 +187,11 @@ pub mod ddc_bucket { /// /// See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema) #[ink(message, payable)] - pub fn bucket_change_params(&mut self, bucket_id: BucketId, params: BucketParams) -> Result<()> { + pub fn bucket_change_params( + &mut self, + bucket_id: BucketId, + params: BucketParams, + ) -> Result<()> { self.message_bucket_change_params(bucket_id, params) } @@ -217,7 +231,7 @@ pub mod ddc_bucket { &mut self, bucket_id: BucketId, public_availability: bool, - ) -> Result<()> { + ) -> Result<()> { self.message_bucket_set_availability(bucket_id, public_availability) } @@ -239,13 +253,21 @@ pub mod ddc_bucket { /// Set permission for the writer of the bucket #[ink(message)] - pub fn bucket_set_writer_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> Result<()> { + pub fn bucket_set_writer_perm( + &mut self, + bucket_id: BucketId, + writer: AccountId, + ) -> Result<()> { self.message_grant_writer_permission(bucket_id, writer) } /// Revoke permission for the writer of the bucket #[ink(message)] - pub fn bucket_revoke_writer_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> Result<()> { + pub fn bucket_revoke_writer_perm( + &mut self, + bucket_id: BucketId, + writer: AccountId, + ) -> Result<()> { self.message_revoke_writer_permission(bucket_id, writer) } @@ -257,13 +279,21 @@ pub mod ddc_bucket { /// Set permission for the reader of the bucket #[ink(message)] - pub fn bucket_set_reader_perm(&mut self, bucket_id: BucketId, reader: AccountId) -> Result<()> { + pub fn bucket_set_reader_perm( + &mut self, + bucket_id: BucketId, + reader: AccountId, + ) -> Result<()> { self.message_grant_reader_permission(bucket_id, reader) } /// Revoke permission for the reader of the bucket #[ink(message)] - pub fn bucket_revoke_reader_perm(&mut self, bucket_id: BucketId, writer: AccountId) -> Result<()> { + pub fn bucket_revoke_reader_perm( + &mut self, + bucket_id: BucketId, + writer: AccountId, + ) -> Result<()> { self.message_revoke_reader_permission(bucket_id, writer) } } @@ -326,7 +356,6 @@ pub mod ddc_bucket { cluster_params: ClusterParams, } - #[ink(event)] #[cfg_attr(feature = "std", derive(PartialEq, Debug, scale_info::TypeInfo))] pub struct ClusterRemoved { @@ -341,7 +370,7 @@ pub mod ddc_bucket { node_key: NodeKey, #[ink(topic)] cluster_id: ClusterId, - status: NodeStatusInCluster + status: NodeStatusInCluster, } #[ink(event)] @@ -351,7 +380,7 @@ pub mod ddc_bucket { cdn_node_key: CdnNodeKey, #[ink(topic)] cluster_id: ClusterId, - status: NodeStatusInCluster + status: NodeStatusInCluster, } /// A vnode was re-assigned to new node. @@ -405,7 +434,6 @@ pub mod ddc_bucket { } impl DdcBucket { - /// Creates a cluster of Storage nodes and CDN nodes. /// /// This endpoint creates a cluster of Storage nodes and CDN nodes with specific parameters. @@ -426,7 +454,7 @@ pub mod ddc_bucket { /// /// # Errors /// - /// * `InvalidClusterParams` error if there is an invalid cluster parameter. + /// * `InvalidClusterParams` error if there is an invalid cluster parameter. #[ink(message, payable)] pub fn cluster_create( &mut self, @@ -508,7 +536,6 @@ pub mod ddc_bucket { self.message_cluster_remove_node(cluster_id, node_key) } - /// Reasignes existing virtual nodes in the targeting cluster. /// /// This endpoint reasignes existing virtual nodes to another physical Storage node within the same cluster. @@ -546,14 +573,9 @@ pub mod ddc_bucket { v_nodes: Vec, new_node_key: NodeKey, ) -> Result<()> { - self.message_cluster_replace_node( - cluster_id, - v_nodes, - new_node_key - ) + self.message_cluster_replace_node(cluster_id, v_nodes, new_node_key) } - /// Reeset a Storage node in the targeting cluster. /// /// This endpoint resets virtual nodes on a physical Storage node in the targeting cluster. @@ -590,14 +612,9 @@ pub mod ddc_bucket { node_key: NodeKey, new_v_nodes: Vec, ) -> Result<()> { - self.message_cluster_reset_node( - cluster_id, - node_key, - new_v_nodes - ) + self.message_cluster_reset_node(cluster_id, node_key, new_v_nodes) } - /// Adds a CDN node to the targeting cluster. /// /// This endpoint adds a CDN node to the targeting cluster. @@ -663,10 +680,10 @@ pub mod ddc_bucket { ) -> Result<()> { self.message_cluster_remove_cdn_node(cluster_id, cdn_node_key) } - + /// Sets parameters for the targeting cluster. /// - /// This endpoint updates [cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. + /// This endpoint updates [cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. /// All cluster parameters must be specified as the endpoint works using SET approach. /// /// # Parameters @@ -688,9 +705,9 @@ pub mod ddc_bucket { /// * `ClusterDoesNotExist` error if the cluster does not exist. #[ink(message, payable)] pub fn cluster_set_params( - &mut self, - cluster_id: ClusterId, - cluster_params: ClusterParams + &mut self, + cluster_id: ClusterId, + cluster_params: ClusterParams, ) -> Result<()> { self.message_cluster_set_params(cluster_id, cluster_params) } @@ -718,10 +735,7 @@ pub mod ddc_bucket { /// * `ClusterDoesNotExist` error if the cluster does not exist. /// * `ClusterIsNotEmpty` error if the removing cluster contains some Storage or CDN nodes. #[ink(message)] - pub fn cluster_remove( - &mut self, - cluster_id: ClusterId, - ) -> Result<()> { + pub fn cluster_remove(&mut self, cluster_id: ClusterId) -> Result<()> { self.message_cluster_remove(cluster_id) } @@ -750,16 +764,12 @@ pub mod ddc_bucket { /// * `NodeIsNotAddedToCluster(ClusterId)` error if the Storage node is not in this cluster. #[ink(message)] pub fn cluster_set_node_status( - &mut self, + &mut self, cluster_id: ClusterId, - node_key: NodeKey, - status_in_cluster: NodeStatusInCluster + node_key: NodeKey, + status_in_cluster: NodeStatusInCluster, ) -> Result<()> { - self.message_cluster_set_node_status( - cluster_id, - node_key, - status_in_cluster - ) + self.message_cluster_set_node_status(cluster_id, node_key, status_in_cluster) } /// Changes CDN node status. @@ -787,19 +797,14 @@ pub mod ddc_bucket { /// * `CdnNodeIsNotAddedToCluster(ClusterId)` error if the CDN node is not in this cluster. #[ink(message)] pub fn cluster_set_cdn_node_status( - &mut self, + &mut self, cluster_id: ClusterId, - cdn_node_key: CdnNodeKey, - status_in_cluster: NodeStatusInCluster + cdn_node_key: CdnNodeKey, + status_in_cluster: NodeStatusInCluster, ) -> Result<()> { - self.message_cluster_set_cdn_node_status( - cluster_id, - cdn_node_key, - status_in_cluster - ) + self.message_cluster_set_cdn_node_status(cluster_id, cdn_node_key, status_in_cluster) } - /// Sets the resource used per virual node in cluster. /// /// This endpoint sets the resource value that is being used by each virtual node in the cluster. @@ -828,17 +833,13 @@ pub mod ddc_bucket { /// * `InsufficientNodeResources` - error if there is not enough resources in a physical node. #[ink(message)] pub fn cluster_set_resource_per_v_node( - &mut self, - cluster_id: ClusterId, - new_resource_per_v_node: Resource + &mut self, + cluster_id: ClusterId, + new_resource_per_v_node: Resource, ) -> Result<()> { - self.message_cluster_set_resource_per_v_node( - cluster_id, - new_resource_per_v_node - ) + self.message_cluster_set_resource_per_v_node(cluster_id, new_resource_per_v_node) } - /// Gets a cluster. /// /// This endpoint gets the targeting cluster along with its parameters, Storage and CDN nodes. @@ -855,14 +856,10 @@ pub mod ddc_bucket { /// /// * `ClusterDoesNotExist` error if the cluster does not exist. #[ink(message)] - pub fn cluster_get( - &self, - cluster_id: ClusterId - ) -> Result { + pub fn cluster_get(&self, cluster_id: ClusterId) -> Result { self.message_cluster_get(cluster_id) } - /// Gets a paginated list of clusters. /// /// This endpoint gets a paginated list of clusters along with their parameters, Storage and CDN nodes. @@ -936,7 +933,6 @@ pub mod ddc_bucket { pub fn cluster_distribute_cdn_revenue(&mut self, cluster_id: ClusterId) -> Result<()> { self.message_cluster_distribute_cdn_revenue(cluster_id) } - } // ---- End Cluster ---- @@ -945,7 +941,12 @@ pub mod ddc_bucket { impl DdcBucket { /// CDN node operator sets the commit for current era. #[ink(message)] - pub fn set_commit(&mut self, cdn_owner: AccountId, cdn_node_key: CdnNodeKey, commit: Commit) -> Result<()> { + pub fn set_commit( + &mut self, + cdn_owner: AccountId, + cdn_node_key: CdnNodeKey, + commit: Commit, + ) -> Result<()> { self.message_set_commit(cdn_owner, cdn_node_key, commit) } @@ -1011,7 +1012,6 @@ pub mod ddc_bucket { } impl DdcBucket { - /// Creates a CDN node /// /// This endpoint creates a CDN node with specific parameters. @@ -1036,9 +1036,9 @@ pub mod ddc_bucket { /// * `InvalidParams(message)` error if there is some invalid configuration parameter. #[ink(message, payable)] pub fn cdn_node_create( - &mut self, - cdn_node_key: CdnNodeKey, - cdn_node_params: CdnNodeParams + &mut self, + cdn_node_key: CdnNodeKey, + cdn_node_params: CdnNodeParams, ) -> Result { self.message_cdn_node_create(cdn_node_key, cdn_node_params) } @@ -1066,16 +1066,13 @@ pub mod ddc_bucket { /// * `CdnNodeDoesNotExist` error if the CDN node does not exist. /// * `CdnNodeIsAddedToCluster(ClusterId)` error if the removing CDN node is added to some cluster. #[ink(message)] - pub fn cdn_node_remove( - &mut self, - cdn_node_key: CdnNodeKey - ) -> Result<()> { + pub fn cdn_node_remove(&mut self, cdn_node_key: CdnNodeKey) -> Result<()> { self.message_remove_cdn_node(cdn_node_key) } /// Sets parameters for the targeting CDN node. /// - /// This endpoint updates [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. + /// This endpoint updates [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. /// All CDN node parameters must be specified as the endpoint works using SET approach. /// /// # Parameters @@ -1097,9 +1094,9 @@ pub mod ddc_bucket { /// * `CdnNodeDoesNotExist` error if the CDN node does not exist. #[ink(message, payable)] pub fn cdn_node_set_params( - &mut self, - cdn_node_key: CdnNodeKey, - cdn_node_params: CdnNodeParams + &mut self, + cdn_node_key: CdnNodeKey, + cdn_node_params: CdnNodeParams, ) -> Result<()> { self.message_cdn_node_set_params(cdn_node_key, cdn_node_params) } @@ -1120,10 +1117,7 @@ pub mod ddc_bucket { /// /// * `CdnNodeDoesNotExist` error if the CDN node does not exist. #[ink(message)] - pub fn cdn_node_get( - &self, - cdn_node_key: CdnNodeKey - ) -> Result { + pub fn cdn_node_get(&self, cdn_node_key: CdnNodeKey) -> Result { self.message_cdn_node_get(cdn_node_key) } @@ -1151,7 +1145,6 @@ pub mod ddc_bucket { ) -> (Vec, u32) { self.message_cdn_node_list(offset, limit, filter_provider_id) } - } // ---- End CDN Node ---- @@ -1185,7 +1178,6 @@ pub mod ddc_bucket { } impl DdcBucket { - /// Creates a Storage node /// /// This endpoint creates a Storage node with specific parameters. @@ -1216,14 +1208,9 @@ pub mod ddc_bucket { node_key: NodeKey, node_params: NodeParams, capacity: Resource, - rent_v_node_per_month: Balance + rent_v_node_per_month: Balance, ) -> Result { - self.message_node_create( - node_key, - node_params, - capacity, - rent_v_node_per_month - ) + self.message_node_create(node_key, node_params, capacity, rent_v_node_per_month) } /// Removes a Storage node. @@ -1249,22 +1236,19 @@ pub mod ddc_bucket { /// * `NodeDoesNotExist` error if the Storage node does not exist. /// * `NodeIsAddedToCluster(ClusterId)` error if the removing Storage node is added to some cluster. #[ink(message)] - pub fn node_remove( - &mut self, - node_key: NodeKey - ) -> Result<()> { + pub fn node_remove(&mut self, node_key: NodeKey) -> Result<()> { self.message_node_remove(node_key) } /// Sets parameters for the targeting Storage node. /// - /// This endpoint updates [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. + /// This endpoint updates [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. /// All Storage node parameters must be specified as the endpoint works using SET approach. /// /// # Parameters /// /// * `node_key` - Public Key associated with the Storage node. - /// * `node_params` - [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. + /// * `node_params` - [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. /// /// # Output /// @@ -1280,9 +1264,9 @@ pub mod ddc_bucket { /// * `NodeDoesNotExist` error if the Storage node does not exist. #[ink(message, payable)] pub fn node_set_params( - &mut self, - node_key: NodeKey, - node_params: NodeParams + &mut self, + node_key: NodeKey, + node_params: NodeParams, ) -> Result<()> { self.message_node_set_params(node_key, node_params) } @@ -1303,10 +1287,7 @@ pub mod ddc_bucket { /// /// * `NodeDoesNotExist` error if the Storage node does not exist. #[ink(message)] - pub fn node_get( - &self, - node_key: NodeKey - ) -> Result { + pub fn node_get(&self, node_key: NodeKey) -> Result { self.message_node_get(node_key) } @@ -1334,7 +1315,6 @@ pub mod ddc_bucket { ) -> (Vec, u32) { self.message_node_list(offset, limit, filter_provider_id) } - } // ---- End Node ---- @@ -1460,11 +1440,7 @@ pub mod ddc_bucket { /// /// No errors. #[ink(message)] - pub fn has_permission( - &self, - account_id: AccountId, - permission: Permission - ) -> bool { + pub fn has_permission(&self, account_id: AccountId, permission: Permission) -> bool { self.perms.has_permission(account_id, permission) } @@ -1490,13 +1466,10 @@ pub mod ddc_bucket { /// /// No errors. The endpoint is idempotent. #[ink(message, payable)] - pub fn grant_trusted_manager_permission( - &mut self, - manager_id: AccountId - ) -> Result<()> { + pub fn grant_trusted_manager_permission(&mut self, manager_id: AccountId) -> Result<()> { self.message_grant_trusted_manager_permission(manager_id) } - + /// Revokes permissions from cluster manager. /// /// This endpoint revokes permissions from a cluster manager to manage Storage or CDN node owner. @@ -1519,13 +1492,9 @@ pub mod ddc_bucket { /// /// No errors. The endpoint is idempotent. #[ink(message)] - pub fn revoke_trusted_manager_permission( - &mut self, - manager_id: AccountId - ) -> Result<()> { + pub fn revoke_trusted_manager_permission(&mut self, manager_id: AccountId) -> Result<()> { self.message_revoke_trusted_manager_permission(manager_id) } - } // ---- End Permissions ---- @@ -1549,7 +1518,6 @@ pub mod ddc_bucket { // ---- Admin ---- impl DdcBucket { - /// Grants any permission. /// /// This endpoint grants any permissions for any account by the Super-admin. @@ -1572,9 +1540,9 @@ pub mod ddc_bucket { /// Returns `OnlySuperAdmin` error if the caller is not the Super-admin. #[ink(message)] pub fn admin_grant_permission( - &mut self, - grantee: AccountId, - permission: Permission + &mut self, + grantee: AccountId, + permission: Permission, ) -> Result<()> { self.message_admin_grant_permission(grantee, permission) } @@ -1601,9 +1569,9 @@ pub mod ddc_bucket { /// Returns `OnlySuperAdmin` error if the caller is not the Super-admin. #[ink(message)] pub fn admin_revoke_permission( - &mut self, - grantee: AccountId, - permission: Permission + &mut self, + grantee: AccountId, + permission: Permission, ) -> Result<()> { self.message_admin_revoke_permission(grantee, permission) } @@ -1633,9 +1601,9 @@ pub mod ddc_bucket { /// * `NodeProviderIsNotSuperAdmin` error if the owner of the targeting node is not the Super-admin. #[ink(message)] pub fn admin_transfer_node_ownership( - &mut self, - node_key: NodeKey, - new_owner: AccountId + &mut self, + node_key: NodeKey, + new_owner: AccountId, ) -> Result<()> { self.message_admin_transfer_node_ownership(node_key, new_owner) } @@ -1665,9 +1633,9 @@ pub mod ddc_bucket { /// * `CdnNodeOwnerIsNotSuperAdmin` error if the owner of the targeting node is not the Super-admin. #[ink(message)] pub fn admin_transfer_cdn_node_ownership( - &mut self, - cdn_node_key: CdnNodeKey, - new_owner: AccountId + &mut self, + cdn_node_key: CdnNodeKey, + new_owner: AccountId, ) -> Result<()> { self.message_admin_transfer_cdn_node_ownership(cdn_node_key, new_owner) } @@ -1682,7 +1650,7 @@ pub mod ddc_bucket { /// Pay the revenues accumulated by the protocol #[ink(message)] - pub fn admin_withdraw_protocol_revenues(&mut self, amount: Balance) -> Result<()> { + pub fn admin_withdraw_protocol_revenues(&mut self, amount: Balance) -> Result<()> { self.message_admin_withdraw_revenues(amount) } @@ -1696,7 +1664,6 @@ pub mod ddc_bucket { pub fn admin_set_protocol_fee_bp(&mut self, protocol_fee_bp: BasisPoints) -> Result<()> { self.message_admin_set_protocol_fee_bp(protocol_fee_bp) } - } // ---- End Admin ---- @@ -1712,26 +1679,27 @@ pub mod ddc_bucket { // ---- Topology ---- impl DdcBucket { - #[ink(message)] pub fn get_v_nodes_by_cluster(&self, cluster_id: ClusterId) -> Vec { self.message_get_v_nodes_by_cluster(cluster_id) } - + #[ink(message)] pub fn get_v_nodes_by_node(&self, node_key: NodeKey) -> Vec { self.message_get_v_nodes_by_node(node_key) } - + #[ink(message)] - pub fn get_node_by_v_node(&self, cluster_id: ClusterId, v_node: VNodeToken) -> Result { + pub fn get_node_by_v_node( + &self, + cluster_id: ClusterId, + v_node: VNodeToken, + ) -> Result { self.message_get_node_by_v_node(cluster_id, v_node) } - } // ---- End Topology ---- - // ---- Constants ---- /// One token with 10 decimals. pub const TOKEN: Balance = 10_000_000_000; @@ -1742,8 +1710,6 @@ pub mod ddc_bucket { pub const DEFAULT_NETWORK_FEE_BP: BasisPoints = 0; // 0 % pub const DEFAULT_CLUSTER_FEE_BP: BasisPoints = 0; // 0 % - - #[derive(Debug, PartialEq, Eq, Encode, Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum Error { @@ -1788,7 +1754,7 @@ pub mod ddc_bucket { InsufficientBalance, InsufficientNodeResources, InsufficientClusterResources, - EraSettingFailed + EraSettingFailed, } pub type Result = core::result::Result; From 9e5e0e470c390a8e5f50d0657f6d0df7a2b33be2 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Tue, 4 Jul 2023 00:29:21 +0200 Subject: [PATCH 87/89] chore(scripts): polkadot.js version is updated --- scripts/sdk/package.json | 4 +- scripts/sdk/src/abi/ddc_bucket.json | 12 +- scripts/sdk/yarn.lock | 619 ++++++++++++++++------------ 3 files changed, 368 insertions(+), 267 deletions(-) diff --git a/scripts/sdk/package.json b/scripts/sdk/package.json index 39ba53bd..93f2f888 100644 --- a/scripts/sdk/package.json +++ b/scripts/sdk/package.json @@ -5,8 +5,8 @@ "main": "src/index.js", "license": "Apache-2.0", "dependencies": { - "@polkadot/api": "8.2.1", - "@polkadot/api-contract": "8.2.1", + "@polkadot/api": "9.4.1", + "@polkadot/api-contract": "9.4.1", "@polkadot/util-crypto": "9.7.2", "lodash": "^4.17.21" } diff --git a/scripts/sdk/src/abi/ddc_bucket.json b/scripts/sdk/src/abi/ddc_bucket.json index 6bf64b60..95f5fbf5 100644 --- a/scripts/sdk/src/abi/ddc_bucket.json +++ b/scripts/sdk/src/abi/ddc_bucket.json @@ -1,6 +1,6 @@ { "source": { - "hash": "0x1caf5ce3e145731b738594770e25507ba8c09066f63328d913f96cb72ad1ba5d", + "hash": "0x3fb93f4d51fa512d9873fb945365bc5e5a3d168a9e745ffc19e0cd4e25ecbb68", "language": "ink! 3.4.0", "compiler": "rustc 1.69.0-nightly" }, @@ -1578,7 +1578,7 @@ "", " # Errors", "", - " * `InvalidClusterParams` error if there is an invalid cluster parameter. " + " * `InvalidClusterParams` error if there is an invalid cluster parameter." ], "label": "cluster_create", "mutates": true, @@ -2006,7 +2006,7 @@ "docs": [ " Sets parameters for the targeting cluster.", "", - " This endpoint updates [cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format. ", + " This endpoint updates [cluster parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#cluster-parameters) in protobuf format.", " All cluster parameters must be specified as the endpoint works using SET approach.", "", " # Parameters", @@ -2835,7 +2835,7 @@ "docs": [ " Sets parameters for the targeting CDN node.", "", - " This endpoint updates [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. ", + " This endpoint updates [CDN node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format.", " All CDN node parameters must be specified as the endpoint works using SET approach.", "", " # Parameters", @@ -3110,13 +3110,13 @@ "docs": [ " Sets parameters for the targeting Storage node.", "", - " This endpoint updates [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. ", + " This endpoint updates [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format.", " All Storage node parameters must be specified as the endpoint works using SET approach.", "", " # Parameters", "", " * `node_key` - Public Key associated with the Storage node.", - " * `node_params` - [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format. ", + " * `node_params` - [Storage node parameters](https://docs.cere.network/ddc/protocols/contract-params-schema#node-params.proto) in protobuf format.", "", " # Output", "", diff --git a/scripts/sdk/yarn.lock b/scripts/sdk/yarn.lock index b01b379f..7012ce2d 100644 --- a/scripts/sdk/yarn.lock +++ b/scripts/sdk/yarn.lock @@ -2,110 +2,136 @@ # yarn lockfile v1 -"@babel/runtime@^7.17.9", "@babel/runtime@^7.18.6", "@babel/runtime@^7.20.6": +"@babel/runtime@^7.18.6", "@babel/runtime@^7.20.6": version "7.21.5" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.5.tgz#8492dddda9644ae3bda3b45eabe87382caee7200" integrity sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q== dependencies: regenerator-runtime "^0.13.11" +"@babel/runtime@^7.19.0", "@babel/runtime@^7.20.13": + version "7.22.5" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec" + integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA== + dependencies: + regenerator-runtime "^0.13.11" + "@noble/hashes@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== +"@noble/hashes@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" + integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== + "@noble/secp256k1@1.6.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.6.0.tgz#602afbbfcfb7e169210469b697365ef740d7e930" integrity sha512-DWSsg8zMHOYMYBqIQi96BQuthZrp98LCeMNcUOaffCIVYQ5yxDbNikLF+H7jEnmNNmXbtVic46iCuVWzar+MgA== -"@polkadot/api-augment@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@polkadot/api-augment/-/api-augment-8.2.1.tgz#27173ecbb700b33d224f4b55a2fa6f5f76d776a1" - integrity sha512-kNS4Ff1KLL6FyR04s4CIR0wVi3I36ErvOUZnZqaHE3DRUBWSzmocAkXaHrwzYDs6nseoL98jtnEkBMRO50gJWw== - dependencies: - "@babel/runtime" "^7.17.9" - "@polkadot/api-base" "8.2.1" - "@polkadot/rpc-augment" "8.2.1" - "@polkadot/types" "8.2.1" - "@polkadot/types-augment" "8.2.1" - "@polkadot/types-codec" "8.2.1" - "@polkadot/util" "^9.0.1" - -"@polkadot/api-base@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@polkadot/api-base/-/api-base-8.2.1.tgz#60dd3aa72d8fd3727822e67c11c190b91af80c1f" - integrity sha512-z614lpNagsuFH47++CNOYaraET4lWRA2Y+d+CqMoWlCgAtKDuqraZfjF7SzYMGp67zSD+FYFSimReWPh5LMV/Q== - dependencies: - "@babel/runtime" "^7.17.9" - "@polkadot/rpc-core" "8.2.1" - "@polkadot/types" "8.2.1" - "@polkadot/util" "^9.0.1" - rxjs "^7.5.5" - -"@polkadot/api-contract@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@polkadot/api-contract/-/api-contract-8.2.1.tgz#ff00472057a2b0566e052d9082ac9ea13cc82916" - integrity sha512-y0HXHg3+8iodcdlyeXSn/ZZ2tuGs0dz8ehp09u6asZLyenWME4mi1ERSg4+WspHcQxR99TgAqfOZpCfDo1Yi8A== - dependencies: - "@babel/runtime" "^7.17.9" - "@polkadot/api" "8.2.1" - "@polkadot/types" "8.2.1" - "@polkadot/types-codec" "8.2.1" - "@polkadot/types-create" "8.2.1" - "@polkadot/util" "^9.0.1" - "@polkadot/util-crypto" "^9.0.1" - rxjs "^7.5.5" - -"@polkadot/api-derive@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-8.2.1.tgz#a4ad04b441d29b52bc0acf51a4872f5ab0d1bfcd" - integrity sha512-rLM99VyZMqsbYZf0ZxEYvKQCKjggJitDklHyemaVP1E2czOI+sKAy5R+oTyOXsAEk5QD2Bh6bLT6eDuuSDvdrA== - dependencies: - "@babel/runtime" "^7.17.9" - "@polkadot/api" "8.2.1" - "@polkadot/api-augment" "8.2.1" - "@polkadot/api-base" "8.2.1" - "@polkadot/rpc-core" "8.2.1" - "@polkadot/types" "8.2.1" - "@polkadot/types-codec" "8.2.1" - "@polkadot/util" "^9.0.1" - "@polkadot/util-crypto" "^9.0.1" - rxjs "^7.5.5" - -"@polkadot/api@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-8.2.1.tgz#dc78650b317467f874d0c381a849b378ace62800" - integrity sha512-zq1sOb1dPIyUwClx5NAqWlhB/b6t6eiSDJyZdSzvWz9XL1YWcd7/m7VtrTcMQbvC8EyMKW09Xiv5G2MEI3bhVw== - dependencies: - "@babel/runtime" "^7.17.9" - "@polkadot/api-augment" "8.2.1" - "@polkadot/api-base" "8.2.1" - "@polkadot/api-derive" "8.2.1" - "@polkadot/keyring" "^9.0.1" - "@polkadot/rpc-augment" "8.2.1" - "@polkadot/rpc-core" "8.2.1" - "@polkadot/rpc-provider" "8.2.1" - "@polkadot/types" "8.2.1" - "@polkadot/types-augment" "8.2.1" - "@polkadot/types-codec" "8.2.1" - "@polkadot/types-create" "8.2.1" - "@polkadot/types-known" "8.2.1" - "@polkadot/util" "^9.0.1" - "@polkadot/util-crypto" "^9.0.1" +"@noble/secp256k1@1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== + +"@polkadot/api-augment@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@polkadot/api-augment/-/api-augment-9.4.1.tgz#2e2d00b0a89eb2b2df8a318b57f6aca4c5e0d402" + integrity sha512-I+jcPAeMUQn0YSs/JZhUsa9+SRcfGjlB0MtzkPb2w1uZhtXgg1bY36q6IXzhEHKxfjjUIjgITp/bSjJWlISzjw== + dependencies: + "@babel/runtime" "^7.19.0" + "@polkadot/api-base" "9.4.1" + "@polkadot/rpc-augment" "9.4.1" + "@polkadot/types" "9.4.1" + "@polkadot/types-augment" "9.4.1" + "@polkadot/types-codec" "9.4.1" + "@polkadot/util" "^10.1.8" + +"@polkadot/api-base@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@polkadot/api-base/-/api-base-9.4.1.tgz#515271d12cf02d816e281dbb189dbbe00d5a9d77" + integrity sha512-APEnF3EviNMI6wKDIqU9xKOpgXhNJoT4ax4qegTqIWltx7aFMLFM8RYPPtMwSF+bm8z5w8aeEJ1H+vVlp4ovQw== + dependencies: + "@babel/runtime" "^7.19.0" + "@polkadot/rpc-core" "9.4.1" + "@polkadot/types" "9.4.1" + "@polkadot/util" "^10.1.8" + rxjs "^7.5.6" + +"@polkadot/api-contract@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@polkadot/api-contract/-/api-contract-9.4.1.tgz#411269749f30c455effaef982443989a6cd775fe" + integrity sha512-wDGwGJhvkLStudmlsDaP6pQr4sjLRxtTrhfFU3paDkmAtOJoiUKWSiX62vGv+YMBoRQGvFGcWil5h8PNtTe45A== + dependencies: + "@babel/runtime" "^7.19.0" + "@polkadot/api" "9.4.1" + "@polkadot/types" "9.4.1" + "@polkadot/types-codec" "9.4.1" + "@polkadot/types-create" "9.4.1" + "@polkadot/util" "^10.1.8" + "@polkadot/util-crypto" "^10.1.8" + rxjs "^7.5.6" + +"@polkadot/api-derive@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@polkadot/api-derive/-/api-derive-9.4.1.tgz#f02f43bc561ec680102531029b2d788f05214eac" + integrity sha512-RgQtiVi+u2fxxleVZ1dxu7FPdj3YMGbwpaBDc9fr2/ys6Jna5myN1ZsGlO7LzUrGGzug1t8HwHmsy9Ssnlod7w== + dependencies: + "@babel/runtime" "^7.19.0" + "@polkadot/api" "9.4.1" + "@polkadot/api-augment" "9.4.1" + "@polkadot/api-base" "9.4.1" + "@polkadot/rpc-core" "9.4.1" + "@polkadot/types" "9.4.1" + "@polkadot/types-codec" "9.4.1" + "@polkadot/util" "^10.1.8" + "@polkadot/util-crypto" "^10.1.8" + rxjs "^7.5.6" + +"@polkadot/api@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@polkadot/api/-/api-9.4.1.tgz#a926312f80a63893a278336a9bacf83c2efde1ad" + integrity sha512-4xjt5M8f5K8dFvlRXGCjQO8ALplR7fG5TbOBmFdebbL9AinZkOCzKZg9J/nCUzwIYns8syjHFgakDchCkIIBTA== + dependencies: + "@babel/runtime" "^7.19.0" + "@polkadot/api-augment" "9.4.1" + "@polkadot/api-base" "9.4.1" + "@polkadot/api-derive" "9.4.1" + "@polkadot/keyring" "^10.1.8" + "@polkadot/rpc-augment" "9.4.1" + "@polkadot/rpc-core" "9.4.1" + "@polkadot/rpc-provider" "9.4.1" + "@polkadot/types" "9.4.1" + "@polkadot/types-augment" "9.4.1" + "@polkadot/types-codec" "9.4.1" + "@polkadot/types-create" "9.4.1" + "@polkadot/types-known" "9.4.1" + "@polkadot/util" "^10.1.8" + "@polkadot/util-crypto" "^10.1.8" eventemitter3 "^4.0.7" - rxjs "^7.5.5" + rxjs "^7.5.6" -"@polkadot/keyring@^9.0.1": - version "9.7.2" - resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-9.7.2.tgz#3e252bdcabce4f4e74b8fbcd98d77bb0205af21e" - integrity sha512-qY5baU1qduwTE04Cyrqtf2pCpsIk7Z5vi45CD9U3cbkKXaJoNUqIpfKoL8Vh/yVJBwhclMdxV9E2rEJs8Iv4bg== +"@polkadot/keyring@^10.1.8": + version "10.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/keyring/-/keyring-10.4.2.tgz#793377fdb9076df0af771df11388faa6be03c70d" + integrity sha512-7iHhJuXaHrRTG6cJDbZE9G+c1ts1dujp0qbO4RfAPmT7YUvphHvAtCKueN9UKPz5+TYDL+rP/jDEaSKU8jl/qQ== dependencies: - "@babel/runtime" "^7.18.6" - "@polkadot/util" "9.7.2" - "@polkadot/util-crypto" "9.7.2" + "@babel/runtime" "^7.20.13" + "@polkadot/util" "10.4.2" + "@polkadot/util-crypto" "10.4.2" + +"@polkadot/networks@10.4.2", "@polkadot/networks@^10.1.8": + version "10.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-10.4.2.tgz#d7878c6aad8173c800a21140bfe5459261724456" + integrity sha512-FAh/znrEvWBiA/LbcT5GXHsCFUl//y9KqxLghSr/CreAmAergiJNT0MVUezC7Y36nkATgmsr4ylFwIxhVtuuCw== + dependencies: + "@babel/runtime" "^7.20.13" + "@polkadot/util" "10.4.2" + "@substrate/ss58-registry" "^1.38.0" -"@polkadot/networks@9.7.2", "@polkadot/networks@^9.0.1": +"@polkadot/networks@9.7.2": version "9.7.2" resolved "https://registry.yarnpkg.com/@polkadot/networks/-/networks-9.7.2.tgz#9064f0578b293245bee263367d6f1674eb06e506" integrity sha512-oMAdF8Y9CLBI0EUZBcycHcvbQQdbkJHevPJ/lwnZXJTaueXuav/Xm2yiFj5J3V8meIjLocURlMawgsAVItXOBQ== @@ -114,110 +140,128 @@ "@polkadot/util" "9.7.2" "@substrate/ss58-registry" "^1.23.0" -"@polkadot/rpc-augment@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@polkadot/rpc-augment/-/rpc-augment-8.2.1.tgz#ad161f9c523ace32e41aa68ad23745d9ac5103f7" - integrity sha512-Fr0wB275SjXqdhY3A4cazKCmOVIIIX3NQSiXiqpsFYMpSgmPPMNwgDPjxngJ7aI3lqMUGGC1sSD4vkSkDntfnQ== - dependencies: - "@babel/runtime" "^7.17.9" - "@polkadot/rpc-core" "8.2.1" - "@polkadot/types" "8.2.1" - "@polkadot/types-codec" "8.2.1" - "@polkadot/util" "^9.0.1" - -"@polkadot/rpc-core@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-8.2.1.tgz#54a0fcce7a58843be60d90317f0c4d0b8486d0a4" - integrity sha512-nRhUHQ5nkbbeFh/lV3OrCHJ/SAgV1KT7onPEVkSGG+OzuyY9yvGsDUbAtqfo+r2kBEDB6RhjV4Sx1HSeNHmQWg== - dependencies: - "@babel/runtime" "^7.17.9" - "@polkadot/rpc-augment" "8.2.1" - "@polkadot/rpc-provider" "8.2.1" - "@polkadot/types" "8.2.1" - "@polkadot/util" "^9.0.1" - rxjs "^7.5.5" - -"@polkadot/rpc-provider@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-8.2.1.tgz#d9471691a0b3d5e385b162087aa420d8cefb97ef" - integrity sha512-aGmwAA588me4DASe01wmkcY75ABVhcRlFvozIIDtvmlCk2/4uWk4RSLMcdbhedK+XQurh1w6W9jKAddAofCAIA== - dependencies: - "@babel/runtime" "^7.17.9" - "@polkadot/keyring" "^9.0.1" - "@polkadot/types" "8.2.1" - "@polkadot/types-support" "8.2.1" - "@polkadot/util" "^9.0.1" - "@polkadot/util-crypto" "^9.0.1" - "@polkadot/x-fetch" "^9.0.1" - "@polkadot/x-global" "^9.0.1" - "@polkadot/x-ws" "^9.0.1" - "@substrate/connect" "0.7.2" +"@polkadot/rpc-augment@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-augment/-/rpc-augment-9.4.1.tgz#ae5563a9850950a84ca986e991e17be663b0278f" + integrity sha512-ZBI5YrVE5U23Zta+XrQt9qYyf0FHgalXvlCzytjNo/VpHhZ371yisBbOuoetyP14rnF+RWux3rgU4Y1c9LNN+Q== + dependencies: + "@babel/runtime" "^7.19.0" + "@polkadot/rpc-core" "9.4.1" + "@polkadot/types" "9.4.1" + "@polkadot/types-codec" "9.4.1" + "@polkadot/util" "^10.1.8" + +"@polkadot/rpc-core@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-core/-/rpc-core-9.4.1.tgz#21c3e74996105c7fee082e6ebb8302deb8b0d86e" + integrity sha512-nGiebijY+DW7qmyB5O0iIlwVpI+m3olWJrMZT0gy7eUehwhsdjWNo3CjePb+EWtdlSjhpcxTwKCc4EaikWQCyQ== + dependencies: + "@babel/runtime" "^7.19.0" + "@polkadot/rpc-augment" "9.4.1" + "@polkadot/rpc-provider" "9.4.1" + "@polkadot/types" "9.4.1" + "@polkadot/util" "^10.1.8" + rxjs "^7.5.6" + +"@polkadot/rpc-provider@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@polkadot/rpc-provider/-/rpc-provider-9.4.1.tgz#3f05f9f70bb36d38503acf99852460cffac29af1" + integrity sha512-JBq049KGpM6pDkgbxiADZG1cuTbBcfEJer466SVp54fGaF7ZfpWN6yb9pQNNkHvvx6rzPnxrTxWpqJXHlI+fmw== + dependencies: + "@babel/runtime" "^7.19.0" + "@polkadot/keyring" "^10.1.8" + "@polkadot/types" "9.4.1" + "@polkadot/types-support" "9.4.1" + "@polkadot/util" "^10.1.8" + "@polkadot/util-crypto" "^10.1.8" + "@polkadot/x-fetch" "^10.1.8" + "@polkadot/x-global" "^10.1.8" + "@polkadot/x-ws" "^10.1.8" + "@substrate/connect" "0.7.13" eventemitter3 "^4.0.7" - mock-socket "^9.1.3" - nock "^13.2.4" - -"@polkadot/types-augment@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@polkadot/types-augment/-/types-augment-8.2.1.tgz#79670f13323d9811ec5552ace8d39a24b6038ba2" - integrity sha512-+uMC4JTYTghhbwyvvdjUnLcV3HeUZOqscfVYPYPtwctblXZRZae77b8TD1H+NqgBhloJPC8I8uBVflRIb+HcpA== - dependencies: - "@babel/runtime" "^7.17.9" - "@polkadot/types" "8.2.1" - "@polkadot/types-codec" "8.2.1" - "@polkadot/util" "^9.0.1" - -"@polkadot/types-codec@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@polkadot/types-codec/-/types-codec-8.2.1.tgz#88fe747e1d94f1b68871494c5ad09d4607f4e060" - integrity sha512-dG5QUCNVmRA8BuQQdxU+2DB4lp+kbO22rDimJMNCr7lOELCIkbo+GFNpWhPInIq+aLrTTAyyv0VguJ3ciQVFJA== - dependencies: - "@babel/runtime" "^7.17.9" - "@polkadot/util" "^9.0.1" - -"@polkadot/types-create@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@polkadot/types-create/-/types-create-8.2.1.tgz#1a8c538bd9f8b3bc03759e1219b894f7d8c4fff6" - integrity sha512-pdzSZgozhe/2EXnnXlxEoBiFwcg19mZ+o0ICdM+cpHayume5C3DrJzIRhQpKu7ndUyEb+MorC5aZn9Cj8Kdp0Q== - dependencies: - "@babel/runtime" "^7.17.9" - "@polkadot/types-codec" "8.2.1" - "@polkadot/util" "^9.0.1" - -"@polkadot/types-known@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-8.2.1.tgz#9b17f711b5d48b4558e2755b9f03e3c20f10ef85" - integrity sha512-9d+LOffogl7HOJ9ooiaOjfbZttF3LgjkVMTU1BQduu5Ln/o6Bk5ARCDeJuSEwYIegtqxrwpxlJabUuUT9xNmew== - dependencies: - "@babel/runtime" "^7.17.9" - "@polkadot/networks" "^9.0.1" - "@polkadot/types" "8.2.1" - "@polkadot/types-codec" "8.2.1" - "@polkadot/types-create" "8.2.1" - "@polkadot/util" "^9.0.1" - -"@polkadot/types-support@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@polkadot/types-support/-/types-support-8.2.1.tgz#2024592d554119246be5b96edbb2b80a2df04c6d" - integrity sha512-vXvcbioDOVGcSpKIq4UrMVfbQPLsLEnhmn0BRGQotACfWGtBqRr1En1SIfSo5nJ/gyBjoq4AUsdUQII2Sa4Drw== - dependencies: - "@babel/runtime" "^7.17.9" - "@polkadot/util" "^9.0.1" - -"@polkadot/types@8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-8.2.1.tgz#6d25ba48d8c925f05155ce1e922b36281b562d24" - integrity sha512-Qvgvxt5GNb9RRXDNIXB9Gu+E4Vw/9aRKw76mamWqFgtRONOJ8l6HgKgWvzsCZ/lBIKLi5NE/BKPIkOhZAWfDmA== - dependencies: - "@babel/runtime" "^7.17.9" - "@polkadot/keyring" "^9.0.1" - "@polkadot/types-augment" "8.2.1" - "@polkadot/types-codec" "8.2.1" - "@polkadot/types-create" "8.2.1" - "@polkadot/util" "^9.0.1" - "@polkadot/util-crypto" "^9.0.1" - rxjs "^7.5.5" - -"@polkadot/util-crypto@9.7.2", "@polkadot/util-crypto@^9.0.1": + mock-socket "^9.1.5" + nock "^13.2.9" + +"@polkadot/types-augment@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@polkadot/types-augment/-/types-augment-9.4.1.tgz#c886597daa3e2304748a6701ac6eb5043dc2bfda" + integrity sha512-3GHoXSSUNVQF1iFJgTWoxo/VM5JLv8kJZjJR8T5mzPjqJQLa1zejkPqF7nvmJq39R/AarrNqg6R0xE6usZAtRw== + dependencies: + "@babel/runtime" "^7.19.0" + "@polkadot/types" "9.4.1" + "@polkadot/types-codec" "9.4.1" + "@polkadot/util" "^10.1.8" + +"@polkadot/types-codec@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@polkadot/types-codec/-/types-codec-9.4.1.tgz#451d0d4207b3fef2141a51a1e9a8d0245236017a" + integrity sha512-S1aFDDK4GL/9SEFYZ6ZAzCvh2QFO/mf3dbTYZLFD7JHQLcbAgTi5E6oz+hWYzsJYW5SzTDW4VdIPoAjY+28UEA== + dependencies: + "@babel/runtime" "^7.19.0" + "@polkadot/util" "^10.1.8" + "@polkadot/x-bigint" "^10.1.8" + +"@polkadot/types-create@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@polkadot/types-create/-/types-create-9.4.1.tgz#1889d74dfb31aa84ecaad40d5c88560c0c51cac0" + integrity sha512-XDGrefz0L8vRl5wjEtiCK8i/kwdcMCqm8vgCmXyMOsZxWkObzK9bex/EhdM/8kMBtXn/b4uQn67ZU89dptMWXw== + dependencies: + "@babel/runtime" "^7.19.0" + "@polkadot/types-codec" "9.4.1" + "@polkadot/util" "^10.1.8" + +"@polkadot/types-known@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@polkadot/types-known/-/types-known-9.4.1.tgz#4b37eaf2886c437725640876d55f6d4af6308b2b" + integrity sha512-1WE+3IEaWaxRvASa6lQgE2bbIaqyesZsArd1QAlsWbOVlV/mSPeRXgBKwF+uDpWOXojZ+oKsOEnBf23BHGdIPg== + dependencies: + "@babel/runtime" "^7.19.0" + "@polkadot/networks" "^10.1.8" + "@polkadot/types" "9.4.1" + "@polkadot/types-codec" "9.4.1" + "@polkadot/types-create" "9.4.1" + "@polkadot/util" "^10.1.8" + +"@polkadot/types-support@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@polkadot/types-support/-/types-support-9.4.1.tgz#7ea34676a5f50d74ccecb20d0dd80176f7ec2bf9" + integrity sha512-5udvaZU/KvEDzhDTcU8Qv9WG/3mu6nwx7m7PqDDywzUo/MAy2zI4OT6JBHcvJIk8Qm3zVQkVftohR8CbF9FeSg== + dependencies: + "@babel/runtime" "^7.19.0" + "@polkadot/util" "^10.1.8" + +"@polkadot/types@9.4.1": + version "9.4.1" + resolved "https://registry.yarnpkg.com/@polkadot/types/-/types-9.4.1.tgz#a713efdb5aa736a736ad186df82dd4c6a82ad0a6" + integrity sha512-vUPHqlBS5neNmI+8IgJxywCL3izdCgd3SrMKWM/xlxzhGh8zfBXaGiRu1sreEk4yuNCAMMWYYDp+eqecZ6wXGA== + dependencies: + "@babel/runtime" "^7.19.0" + "@polkadot/keyring" "^10.1.8" + "@polkadot/types-augment" "9.4.1" + "@polkadot/types-codec" "9.4.1" + "@polkadot/types-create" "9.4.1" + "@polkadot/util" "^10.1.8" + "@polkadot/util-crypto" "^10.1.8" + rxjs "^7.5.6" + +"@polkadot/util-crypto@10.4.2", "@polkadot/util-crypto@^10.1.8": + version "10.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-10.4.2.tgz#871fb69c65768bd48c57bb5c1f76a85d979fb8b5" + integrity sha512-RxZvF7C4+EF3fzQv8hZOLrYCBq5+wA+2LWv98nECkroChY3C2ZZvyWDqn8+aonNULt4dCVTWDZM0QIY6y4LUAQ== + dependencies: + "@babel/runtime" "^7.20.13" + "@noble/hashes" "1.2.0" + "@noble/secp256k1" "1.7.1" + "@polkadot/networks" "10.4.2" + "@polkadot/util" "10.4.2" + "@polkadot/wasm-crypto" "^6.4.1" + "@polkadot/x-bigint" "10.4.2" + "@polkadot/x-randomvalues" "10.4.2" + "@scure/base" "1.1.1" + ed2curve "^0.3.0" + tweetnacl "^1.0.3" + +"@polkadot/util-crypto@9.7.2": version "9.7.2" resolved "https://registry.yarnpkg.com/@polkadot/util-crypto/-/util-crypto-9.7.2.tgz#0a097f4e197cd344d101ab748a740c2d99a4c5b9" integrity sha512-tfz6mJtPwoNteivKCmR+QklC4mr1/hGZRsDJLWKaFhanDinYZ3V2pJM1EbCI6WONLuuzlTxsDXjAffWzzRqlPA== @@ -234,7 +278,20 @@ ed2curve "^0.3.0" tweetnacl "^1.0.3" -"@polkadot/util@9.7.2", "@polkadot/util@^9.0.1": +"@polkadot/util@10.4.2", "@polkadot/util@^10.1.8": + version "10.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-10.4.2.tgz#df41805cb27f46b2b4dad24c371fa2a68761baa1" + integrity sha512-0r5MGICYiaCdWnx+7Axlpvzisy/bi1wZGXgCSw5+ZTyPTOqvsYRqM2X879yxvMsGfibxzWqNzaiVjToz1jvUaA== + dependencies: + "@babel/runtime" "^7.20.13" + "@polkadot/x-bigint" "10.4.2" + "@polkadot/x-global" "10.4.2" + "@polkadot/x-textdecoder" "10.4.2" + "@polkadot/x-textencoder" "10.4.2" + "@types/bn.js" "^5.1.1" + bn.js "^5.2.1" + +"@polkadot/util@9.7.2": version "9.7.2" resolved "https://registry.yarnpkg.com/@polkadot/util/-/util-9.7.2.tgz#0f97fa92b273e6ce4b53fe869a957ac99342007d" integrity sha512-ivTmA+KkPCq5i3O0Gk+dTds/hwdwlYCh89aKfeaG9ni3XHUbbuBgTqHneo648HqxwAwSAyiDiwE9EdXrzAdO4Q== @@ -280,7 +337,7 @@ "@babel/runtime" "^7.20.6" "@polkadot/wasm-util" "6.4.1" -"@polkadot/wasm-crypto@^6.2.2": +"@polkadot/wasm-crypto@^6.2.2", "@polkadot/wasm-crypto@^6.4.1": version "6.4.1" resolved "https://registry.yarnpkg.com/@polkadot/wasm-crypto/-/wasm-crypto-6.4.1.tgz#79310e23ad1ca62362ba893db6a8567154c2536a" integrity sha512-FH+dcDPdhSLJvwL0pMLtn/LIPd62QDPODZRCmDyw+pFjLOMaRBc7raomWUOqyRWJTnqVf/iscc2rLVLNMyt7ag== @@ -299,6 +356,14 @@ dependencies: "@babel/runtime" "^7.20.6" +"@polkadot/x-bigint@10.4.2", "@polkadot/x-bigint@^10.1.8": + version "10.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-bigint/-/x-bigint-10.4.2.tgz#7eb2ec732259df48b5a00f07879a1331e05606ec" + integrity sha512-awRiox+/XSReLzimAU94fPldowiwnnMUkQJe8AebYhNocAj6SJU00GNoj6j6tAho6yleOwrTJXZaWFBaQVJQNg== + dependencies: + "@babel/runtime" "^7.20.13" + "@polkadot/x-global" "10.4.2" + "@polkadot/x-bigint@9.7.2": version "9.7.2" resolved "https://registry.yarnpkg.com/@polkadot/x-bigint/-/x-bigint-9.7.2.tgz#ec79977335dce173a81e45247bdfd46f3b301702" @@ -307,23 +372,38 @@ "@babel/runtime" "^7.18.6" "@polkadot/x-global" "9.7.2" -"@polkadot/x-fetch@^9.0.1": - version "9.7.2" - resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-9.7.2.tgz#bc4091603114a4182ab06b8d7d127a3dd730cf48" - integrity sha512-ysXpPNq2S+L98hKow3d59prU4QFRg5N86pMkJdONc4VxtKITVY2MfdLVCqfEOOFuuwCzE7Sfmx53I4XpDgbP7A== +"@polkadot/x-fetch@^10.1.8": + version "10.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-fetch/-/x-fetch-10.4.2.tgz#bc6ba70de71a252472fbe36180511ed920e05f05" + integrity sha512-Ubb64yaM4qwhogNP+4mZ3ibRghEg5UuCYRMNaCFoPgNAY8tQXuDKrHzeks3+frlmeH9YRd89o8wXLtWouwZIcw== dependencies: - "@babel/runtime" "^7.18.6" - "@polkadot/x-global" "9.7.2" + "@babel/runtime" "^7.20.13" + "@polkadot/x-global" "10.4.2" "@types/node-fetch" "^2.6.2" - node-fetch "^2.6.7" + node-fetch "^3.3.0" + +"@polkadot/x-global@10.4.2", "@polkadot/x-global@^10.1.8": + version "10.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-10.4.2.tgz#5662366e3deda0b4c8f024b2d902fa838f9e60a4" + integrity sha512-g6GXHD/ykZvHap3M6wh19dO70Zm43l4jEhlxf5LtTo5/0/UporFCXr2YJYZqfbn9JbQwl1AU+NroYio+vtJdiA== + dependencies: + "@babel/runtime" "^7.20.13" -"@polkadot/x-global@9.7.2", "@polkadot/x-global@^9.0.1": +"@polkadot/x-global@9.7.2": version "9.7.2" resolved "https://registry.yarnpkg.com/@polkadot/x-global/-/x-global-9.7.2.tgz#9847fd1da13989f321ca621e85477ba70fd8d55a" integrity sha512-3NN5JhjosaelaFWBJSlv9mb/gDAlt7RuZ8NKlOjB+LQHd9g6ZbnYi5wwjW+i/x/3E4IVbBx66uvWgNaw7IBrkg== dependencies: "@babel/runtime" "^7.18.6" +"@polkadot/x-randomvalues@10.4.2": + version "10.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-10.4.2.tgz#895f1220d5a4522a83d8d5014e3c1e03b129893e" + integrity sha512-mf1Wbpe7pRZHO0V3V89isPLqZOy5XGX2bCqsfUWHgb1NvV1MMx5TjVjdaYyNlGTiOkAmJKlOHshcfPU2sYWpNg== + dependencies: + "@babel/runtime" "^7.20.13" + "@polkadot/x-global" "10.4.2" + "@polkadot/x-randomvalues@9.7.2": version "9.7.2" resolved "https://registry.yarnpkg.com/@polkadot/x-randomvalues/-/x-randomvalues-9.7.2.tgz#d580b0e9149ea22b2afebba5d7b1368371f7086d" @@ -332,6 +412,14 @@ "@babel/runtime" "^7.18.6" "@polkadot/x-global" "9.7.2" +"@polkadot/x-textdecoder@10.4.2": + version "10.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-10.4.2.tgz#93202f3e5ad0e7f75a3fa02d2b8a3343091b341b" + integrity sha512-d3ADduOKUTU+cliz839+KCFmi23pxTlabH7qh7Vs1GZQvXOELWdqFOqakdiAjtMn68n1KVF4O14Y+OUm7gp/zA== + dependencies: + "@babel/runtime" "^7.20.13" + "@polkadot/x-global" "10.4.2" + "@polkadot/x-textdecoder@9.7.2": version "9.7.2" resolved "https://registry.yarnpkg.com/@polkadot/x-textdecoder/-/x-textdecoder-9.7.2.tgz#c94ea6c8f510fdf579659248ede9421854e32b42" @@ -340,6 +428,14 @@ "@babel/runtime" "^7.18.6" "@polkadot/x-global" "9.7.2" +"@polkadot/x-textencoder@10.4.2": + version "10.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-10.4.2.tgz#cd2e6c8a66b0b400a73f0164e99c510fb5c83501" + integrity sha512-mxcQuA1exnyv74Kasl5vxBq01QwckG088lYjc3KwmND6+pPrW2OWagbxFX5VFoDLDAE+UJtnUHsjdWyOTDhpQA== + dependencies: + "@babel/runtime" "^7.20.13" + "@polkadot/x-global" "10.4.2" + "@polkadot/x-textencoder@9.7.2": version "9.7.2" resolved "https://registry.yarnpkg.com/@polkadot/x-textencoder/-/x-textencoder-9.7.2.tgz#2ae29fa5ca2c0353e7a1913eef710b2d45bdf0b2" @@ -348,13 +444,13 @@ "@babel/runtime" "^7.18.6" "@polkadot/x-global" "9.7.2" -"@polkadot/x-ws@^9.0.1": - version "9.7.2" - resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-9.7.2.tgz#b35470b487d19be48c1fe39e1c73c623bf548b7e" - integrity sha512-yF2qKL00SGivbima22jxoBNYCZFI8Ph7dmnVm7fDztVtO8Fc2x30Lj3a8+qsSOrynLyJHAh2bjjQxpPmDCB9tw== +"@polkadot/x-ws@^10.1.8": + version "10.4.2" + resolved "https://registry.yarnpkg.com/@polkadot/x-ws/-/x-ws-10.4.2.tgz#4e9d88f37717570ccf942c6f4f63b06260f45025" + integrity sha512-3gHSTXAWQu1EMcMVTF5QDKHhEHzKxhAArweEyDXE7VsgKUP/ixxw4hVZBrkX122iI5l5mjSiooRSnp/Zl3xqDQ== dependencies: - "@babel/runtime" "^7.18.6" - "@polkadot/x-global" "9.7.2" + "@babel/runtime" "^7.20.13" + "@polkadot/x-global" "10.4.2" "@types/websocket" "^1.0.5" websocket "^1.0.34" @@ -363,35 +459,39 @@ resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== -"@substrate/connect-extension-protocol@^1.0.0": +"@substrate/connect-extension-protocol@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@substrate/connect-extension-protocol/-/connect-extension-protocol-1.0.1.tgz#fa5738039586c648013caa6a0c95c43265dbe77d" integrity sha512-161JhCC1csjH3GE5mPLEd7HbWtwNSPJBg3p1Ksz9SFlTzj/bgEwudiRN2y5i0MoLGCIJRYKyKGMxVnd29PzNjg== -"@substrate/connect@0.7.2": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@substrate/connect/-/connect-0.7.2.tgz#a2440a7a85a75acbc839745b301d5b8b81cbac5d" - integrity sha512-8GWdrN7qbClYLa9LmETJnywT5fknEQeMw+QKvkUMvsHKegHD0Zkhi0K484mKxRN9RGwcPsKHPj1gMk8xlZuJ9g== +"@substrate/connect@0.7.13": + version "0.7.13" + resolved "https://registry.yarnpkg.com/@substrate/connect/-/connect-0.7.13.tgz#b87e6e9c60a4d7c5c945142e168e413f91bf6580" + integrity sha512-mGvvxLVVm2Zziff8SpTybeIy+jq0LN81kPqDp/bGwtxAnRctbCsERChAu4Q5HN27cCjI1iNdzSz5ihF/DP5SdQ== dependencies: - "@substrate/connect-extension-protocol" "^1.0.0" - "@substrate/smoldot-light" "0.6.15" + "@substrate/connect-extension-protocol" "^1.0.1" + "@substrate/smoldot-light" "0.6.33" eventemitter3 "^4.0.7" -"@substrate/smoldot-light@0.6.15": - version "0.6.15" - resolved "https://registry.yarnpkg.com/@substrate/smoldot-light/-/smoldot-light-0.6.15.tgz#f3fd2a9fa2e3a579d2bf0c13590fb48db4935f9f" - integrity sha512-c2tJCSp9Litsn/p8wY1FfEqIkJI8Peh89BU7T43bruWRO2SSgLVh0cIVbOCY4en90tIOX4W0CueRWFBRQz7BjQ== +"@substrate/smoldot-light@0.6.33": + version "0.6.33" + resolved "https://registry.yarnpkg.com/@substrate/smoldot-light/-/smoldot-light-0.6.33.tgz#887e5af3d1dada334d8d564f8cd3a93bdf7139bf" + integrity sha512-b1bgIcd6369Xa1Y2MelBD3xmyX2FeHnjq8xS0ohy5uC6bR1v6kEkEyCbcIJE1+GlwDzlfaNxbJjwJPIv8FaRYA== dependencies: - buffer "^6.0.1" pako "^2.0.4" - websocket "^1.0.32" + ws "^8.8.1" "@substrate/ss58-registry@^1.23.0": version "1.40.0" resolved "https://registry.yarnpkg.com/@substrate/ss58-registry/-/ss58-registry-1.40.0.tgz#2223409c496271df786c1ca8496898896595441e" integrity sha512-QuU2nBql3J4KCnOWtWDw4n1K4JU0T79j54ZZvm/9nhsX6AIar13FyhsaBfs6QkJ2ixTQAnd7TocJIoJRWbqMZA== -"@types/bn.js@^5.1.0": +"@substrate/ss58-registry@^1.38.0": + version "1.41.0" + resolved "https://registry.yarnpkg.com/@substrate/ss58-registry/-/ss58-registry-1.41.0.tgz#dd18e132f44b73c3cd31cf0db489c10af70bef36" + integrity sha512-TLz5VkEaJRNFzf1Oiix9gqknKer3aKbLfjK9XHBFCIhdxlQpI+S6lZGu3wT4DHAGXPakYfXb8+9ZIOtWLcQ/2Q== + +"@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": version "5.1.1" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.1.tgz#b51e1b55920a4ca26e9285ff79936bbdec910682" integrity sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g== @@ -423,24 +523,11 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== -base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - bn.js@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== -buffer@^6.0.1: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - bufferutil@^4.0.1: version "4.0.7" resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.7.tgz#60c0d19ba2c992dd8273d3f73772ffc894c153ad" @@ -463,6 +550,11 @@ d@1, d@^1.0.1: es5-ext "^0.10.50" type "^1.0.1" +data-uri-to-buffer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e" + integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A== + debug@^2.2.0: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -527,6 +619,14 @@ ext@^1.1.2: dependencies: type "^2.7.2" +fetch-blob@^3.1.2, fetch-blob@^3.1.4: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" + integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== + dependencies: + node-domexception "^1.0.0" + web-streams-polyfill "^3.0.3" + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -536,10 +636,12 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -ieee754@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +formdata-polyfill@^4.0.10: + version "4.0.10" + resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" + integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== + dependencies: + fetch-blob "^3.1.2" ip-regex@^4.3.0: version "4.3.0" @@ -573,7 +675,7 @@ mime-types@^2.1.12: dependencies: mime-db "1.52.0" -mock-socket@^9.1.3: +mock-socket@^9.1.5: version "9.2.1" resolved "https://registry.yarnpkg.com/mock-socket/-/mock-socket-9.2.1.tgz#cc9c0810aa4d0afe02d721dcb2b7e657c00e2282" integrity sha512-aw9F9T9G2zpGipLLhSNh6ZpgUyUl4frcVmRN08uE1NWPWg43Wx6+sGPDbQ7E5iFZZDJW5b5bypMeAEHqTbIFag== @@ -593,7 +695,7 @@ next-tick@^1.1.0: resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ== -nock@^13.2.4: +nock@^13.2.9: version "13.3.1" resolved "https://registry.yarnpkg.com/nock/-/nock-13.3.1.tgz#f22d4d661f7a05ebd9368edae1b5dc0a62d758fc" integrity sha512-vHnopocZuI93p2ccivFyGuUfzjq2fxNyNurp7816mlT5V5HF4SzXu8lvLrVzBbNqzs+ODooZ6OksuSUNM7Njkw== @@ -603,12 +705,19 @@ nock@^13.2.4: lodash "^4.17.21" propagate "^2.0.0" -node-fetch@^2.6.7: - version "2.6.11" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25" - integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w== +node-domexception@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" + integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== + +node-fetch@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.1.tgz#b3eea7b54b3a48020e46f4f88b9c5a7430d20b2e" + integrity sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow== dependencies: - whatwg-url "^5.0.0" + data-uri-to-buffer "^4.0.0" + fetch-blob "^3.1.4" + formdata-polyfill "^4.0.10" node-gyp-build@^4.3.0: version "4.6.0" @@ -630,18 +739,13 @@ regenerator-runtime@^0.13.11: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== -rxjs@^7.5.5: +rxjs@^7.5.6: version "7.8.1" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== dependencies: tslib "^2.1.0" -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - tslib@^2.1.0: version "2.5.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.2.tgz#1b6f07185c881557b0ffa84b111a0106989e8338" @@ -676,12 +780,12 @@ utf-8-validate@^5.0.2: dependencies: node-gyp-build "^4.3.0" -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== +web-streams-polyfill@^3.0.3: + version "3.2.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" + integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== -websocket@^1.0.32, websocket@^1.0.34: +websocket@^1.0.34: version "1.0.34" resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.34.tgz#2bdc2602c08bf2c82253b730655c0ef7dcab3111" integrity sha512-PRDso2sGwF6kM75QykIesBijKSVceR6jL2G8NGYyq2XrItNC2P5/qL5XeR056GhA+Ly7JMFvJb9I312mJfmqnQ== @@ -693,13 +797,10 @@ websocket@^1.0.32, websocket@^1.0.34: utf-8-validate "^5.0.2" yaeti "^0.0.6" -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" +ws@^8.8.1: + version "8.13.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0" + integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA== yaeti@^0.0.6: version "0.0.6" From f9aaa39043983fa3ace72fb1d584bb2574e05b2e Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Tue, 4 Jul 2023 01:12:27 +0200 Subject: [PATCH 88/89] chore(scripts): duplicated scripts removed --- bucket/scripts/.gitignore | 2 - bucket/scripts/config.js | 139 - bucket/scripts/init.js | 129 - bucket/scripts/metadata.json | 4959 ------------------------------ bucket/scripts/package-lock.json | 789 ----- bucket/scripts/package.json | 8 - 6 files changed, 6026 deletions(-) delete mode 100644 bucket/scripts/.gitignore delete mode 100644 bucket/scripts/config.js delete mode 100644 bucket/scripts/init.js delete mode 100644 bucket/scripts/metadata.json delete mode 100644 bucket/scripts/package-lock.json delete mode 100644 bucket/scripts/package.json diff --git a/bucket/scripts/.gitignore b/bucket/scripts/.gitignore deleted file mode 100644 index 1929c324..00000000 --- a/bucket/scripts/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules/ -secrets.txt diff --git a/bucket/scripts/config.js b/bucket/scripts/config.js deleted file mode 100644 index 0323cfe1..00000000 --- a/bucket/scripts/config.js +++ /dev/null @@ -1,139 +0,0 @@ -const GEN = 0x10000000000000000n; // UINT64_MAX - -export const config = { - devnet: { - ws_provider: "wss://archive.devnet.cere.network/ws", - contract_address: "6SfBsKbfPUTN35GCcqAHSMY4MemedK2A73VeJ34Z2FV6PB4r", - cluster: { - 1n: { - param: { replicationFactor: 3 }, - vnodes: [ [0n], [GEN / 4n], [GEN * 2n / 4n], [GEN * 3n / 4n] ], - storage_nodes: [1n, 2n, 3n, 4n], - }, - }, - storage_node_params: [ - { url: `https://node-0.v2.storage.devnet.cere.network` }, - { url: `https://node-1.v2.storage.devnet.cere.network` }, - { url: `https://node-2.v2.storage.devnet.cere.network` }, - { url: `https://node-3.v2.storage.devnet.cere.network` }, - ], - cdn_cluster: { - 0n: { - cdn_nodes: [1n, 2n, 3n, 4n], - }, - }, - cdn_node_params: [ - { - url: `https://node-0.v2.cdn.devnet.cere.network`, - publicKey: "0x1c4a1b081af8dd09096ebb6e7ad61dd549ac2931cdb2b1216589094ad71ca90b", - }, - { - url: `https://node-1.v2.cdn.devnet.cere.network`, - publicKey: "0x3ec2ec407053acdfe8137d7105e90294f2e0e5f5fe5420fd3172142671dbc25f", - }, - { - url: `https://node-2.v2.cdn.devnet.cere.network`, - publicKey: "0x20e448c403d3f009ec309394d3aab828c3dbf0d2cc8047f01dded984ec992b41", - }, - { - url: `https://node-3.v2.cdn.devnet.cere.network`, - publicKey: "0xd2f93cea79e37cfc9e5f78cd3e51b989afb1e257adcbbae00b8cd081539e9f13", - } - ], - }, - - testnet: { - ws_provider: "wss://archive.devnet.cere.network/ws", - // contract_address: "6R2PF5gzKYbNkNLymTr8YNeQgWqNkE6azspwaMLZF2UHc1sg", - contract_address: "6UWDf6rEgSDFRr1h2pMdCbifowTDK64yRkDR6nc3C1cjL82e", - cluster: { - 1n: { - storage_nodes: [1n, 2n, 3n], - vnodes: [ [0n], [GEN / 3n], [GEN * 2n / 3n] ], - param: { replicationFactor: 3 }, - }, - 2n: { - storage_nodes: [4n, 5n, 6n], - vnodes: [ [0n], [GEN / 3n], [GEN * 2n / 3n] ], - param: { replicationFactor: 3 }, - }, - }, - storage_node_params: [ - { url: `https://node-0.v2.us.storage.testnet.cere.network` }, - { url: `https://node-1.v2.us.storage.testnet.cere.network` }, - { url: `https://node-2.v2.us.storage.testnet.cere.network` }, - { url: `https://node-0.v2.eu.storage.testnet.cere.network` }, - { url: `https://node-1.v2.eu.storage.testnet.cere.network` }, - { url: `https://node-2.v2.eu.storage.testnet.cere.network` }, - ], - cdn_cluster: { - 0n: { - cdn_nodes: [1n, 2n], - }, - 1n: { - cdn_nodes: [3n, 4n], - }, - 2n: { - cdn_nodes: [5n, 6n], - }, - }, - cdn_node_params: [ - { - url: `https://node-0.v2.us.cdn.testnet.cere.network`, - publicKey: "0x089522cee0567ff8e072c9efbd5cb4e05fe47cdab8340816be9d6f60538e8645", - }, - { - url: `https://node-1.v2.us.cdn.testnet.cere.network`, - publicKey: "0x7693cbc6a6f3fff67d4eb29bb07bc018e1eee43618d03e6c0a91b0b3e79f272d", - }, - { - url: `https://node-0.v2.eu.cdn.testnet.cere.network`, - publicKey: "0xdce47cdd1da69c19261b72e3c58e93d78e49d1ac20a566b535cb9bcf9d197958", - }, - { - url: `https://node-1.v2.eu.cdn.testnet.cere.network`, - publicKey: "0xb8541743735ffba6877b214925a9ec07c813369bb36b49ee5849b1fea0f9dd55", - }, - { - url: `https://node-0.unmarshal.v2.us.cdn.testnet.cere.network`, - publicKey: "0x685168b78deb42eebf01e38d18c9302f032c50e544d56c1c4f86b13b0a2ad40a", - }, - { - url: `https://node-1.unmarshal.v2.us.cdn.testnet.cere.network`, - publicKey: "0xeeb3683dcd43e9c7f8759b1dce2440d767ae1c51dec05b584d785e24997cb947", - }, - ], - }, - - mainnet: { - ws_provider: "wss://archive.testnet.cere.network/ws", - contract_address: "6So8eqxMyWAxJ4ZZ2wCcJym7Cy6BYkc4V8GZZD9wgdCqWMQB", - cluster: { - 1n: { - param: { replicationFactor: 3 }, - vnodes: [ [0n], [GEN / 3n], [GEN * 2n / 3n] ], - storage_nodes: [1n, 2n, 3n], - }, - }, - storage_node_params: [ - { url: `https://node-0.v2.us.storage.mainnet.cere.network` }, - { url: `https://node-1.v2.us.storage.mainnet.cere.network` }, - { url: `https://node-2.v2.us.storage.mainnet.cere.network` }, - ], - cdn_cluster: { - 0n: { - cdn_nodes: [1n, 2n], - }, - }, - cdn_node_params: [ - { - url: `https://node-0.v2.us.cdn.mainnet.cere.network`, - publicKey: "0x86af4db1e433ad221b6fa3c1a9fc4de694ab59408ca57584e50d8fd420e7b45b", - }, - { - url: `https://node-1.v2.us.cdn.mainnet.cere.network`, - publicKey: "0x9a9fb6c479ef7c8f3af54dc0720f08a73d532815d525aa8d69d965e56512440e", - }, - ], - }, -}; diff --git a/bucket/scripts/init.js b/bucket/scripts/init.js deleted file mode 100644 index 281fe009..00000000 --- a/bucket/scripts/init.js +++ /dev/null @@ -1,129 +0,0 @@ -import { config } from './config.js'; -import * as fs from 'fs'; - -import { ContractPromise } from '@polkadot/api-contract'; -import { ApiPromise, WsProvider, Keyring } from '@polkadot/api'; -import { cryptoWaitReady, mnemonicGenerate } from "@polkadot/util-crypto"; - -const INIT_ENV = process.env.INIT_ENV; -const SUPERADMIN_MNEMONIC = process.env.SUPERADMIN; -const CERE = 10_000_000_000n; - -const txOptions = { - storageDepositLimit: null, - gasLimit: 100_000_000_000n, -}; - -async function signAndSendPromise(txn, signer) { - return new Promise((res, rej) => { - txn - .signAndSend(signer, ({ events = [], status, blockNumber }) => { - if (status.isInvalid) { - console.log(" Transaction invalid"); - rej("Transaction invalid"); - } else if (status.isReady) { - console.log(" Transaction is ready"); - } else if (status.isBroadcast) { - console.log(" Transaction has been broadcasted"); - } else if (status.isInBlock) { - const blockHash = status.asInBlock.toHex(); - console.log(` Transaction is in block: ${blockHash} of ${blockNumber}`); - } else if (status.isFinalized) { - const blockHash = status.asFinalized.toHex(); - console.log(` Transaction has been included in blockHash ${blockHash} of ${blockNumber}`); - const treasuryDeposit = events.find( - (event) => event.event.toHuman().method === "Deposit" && event.event.toHuman().section === "treasury", - ); - const txFee = treasuryDeposit ? treasuryDeposit.event.toHuman().data.value : undefined; - const txFeeParsed = txFee ? (parseFloat(txFee.replace(" mCERE", "")) / 1000) * 2 : undefined; - - if (events.find(event => event.event.toHuman().method === "ExtrinsicSuccess")) res({ blockHash, txFeeParsed, events }); - else rej("No success found: " + blockHash); - } - }) - .catch((err) => rej(err)); - }); -} - -function createUser() { - const keyring = new Keyring({ type: "sr25519" }); - const mnemonic = mnemonicGenerate(12); - const account = keyring.addFromUri(mnemonic); - - return { - mnemonic: mnemonic, - address: account.address, - addressBase64: Buffer.from(account.publicKey).toString("base64"), - }; -} - -const cfg = config[INIT_ENV]; -if (cfg === undefined) { - console.error("Please provide INIT_ENV as one of ", Object.keys(config)); - process.exit(-1); -} -console.log(cfg); - -await cryptoWaitReady(); -const keyring = new Keyring({ type: "sr25519" }); -const alice = keyring.addFromUri("//Alice"); -const sadmin = keyring.addFromUri(SUPERADMIN_MNEMONIC); -console.log(`Superadmin: ${sadmin.address}`); - -// Contract metadata -const metadata = fs.readFileSync('./metadata.json', 'utf8'); - -// Construct -const wsProvider = new WsProvider(cfg.ws_provider); -const api = await ApiPromise.create({ provider: wsProvider }); -const contract = new ContractPromise(api, metadata, cfg.contract_address); - -console.log("1. adminGrantPermission"); -const res = await signAndSendPromise(await contract.tx.adminGrantPermission(txOptions, sadmin.address, "SuperAdmin"), sadmin); - -console.log("2. accountSetUsdPerCere"); -await signAndSendPromise(await contract.tx.accountSetUsdPerCere(txOptions, 1000n * CERE), sadmin); - -console.log("3. cdnNodeTrustManager"); -await signAndSendPromise(await contract.tx.cdnNodeTrustManager(txOptions, sadmin.address), sadmin); - -console.log("4. nodeTrustManager"); -await signAndSendPromise(await contract.tx.nodeTrustManager(txOptions, sadmin.address), sadmin); - -console.log("5. cdnNodeCreate"); -for (let i = 0; i < cfg.cdn_node_params.length; i++) { - await signAndSendPromise(await contract.tx.cdnNodeCreate(txOptions, JSON.stringify(cfg.cdn_node_params[i])), sadmin); -} - -for (let id in cfg.cdn_cluster) { - const clu = cfg.cdn_cluster[id]; - console.log("6. cdnClusterCreate, cluster: ", id, clu); - await signAndSendPromise(await contract.tx.cdnClusterCreate(txOptions, clu.cdn_nodes), sadmin); -} - -console.log("7. nodeCreate"); -for (let i = 0; i < cfg.storage_node_params.length; i++) { - const param = JSON.stringify(cfg.storage_node_params[i]); - const user = createUser(); - fs.appendFileSync('secrets.txt', `${user.address}: ${user.mnemonic} -- ${INIT_ENV} storage ${i}\n`); - console.log(` node ${i}: address ${user.address}, param ${param}`); - await signAndSendPromise(await contract.tx.nodeCreate(txOptions, 1n * CERE, param, 100000n, "ACTIVE", user.address), sadmin); -} - -for (let id in cfg.cluster) { - const clu = cfg.cluster[id]; - - console.log("8. clusterCreate, cluster: ", id, clu); - await signAndSendPromise(await contract.tx.clusterCreate(txOptions, alice.address, clu.vnodes, clu.storage_nodes, JSON.stringify(clu.param)), sadmin); - - console.log("9. clusterReserveResource, cluster: ", id); - await signAndSendPromise(await contract.tx.clusterReserveResource(txOptions, id, 100000n), sadmin); -} - -// console.log("cdnNodeChangeParams"); -// for (let i = 0; i < cfg.cdn_node_params.length; i++) { -// await signAndSendPromise(await contract.tx.cdnNodeChangeParams(txOptions, i+1, JSON.stringify(cfg.cdn_node_params[i])), sadmin); -// } - -//console.log(res.events.map(event => event.event.toHuman())); -process.exit(0); diff --git a/bucket/scripts/metadata.json b/bucket/scripts/metadata.json deleted file mode 100644 index 5233dd85..00000000 --- a/bucket/scripts/metadata.json +++ /dev/null @@ -1,4959 +0,0 @@ -{ - "source": { - "hash": "0x17173e6d800d4555fa6b27c1cb7a5bf509796c993c1ed7e1206e8ef27c21fb48", - "language": "ink! 3.4.0", - "compiler": "rustc 1.69.0-nightly" - }, - "contract": { - "name": "ddc_bucket", - "version": "0.5.2", - "authors": [ - "Aurélien Nicolas " - ], - "description": "DDC v2 Smart Contracts -- Orchestrate the network around clusters and buckets", - "license": "Apache-2.0" - }, - "V3": { - "spec": { - "constructors": [ - { - "args": [], - "docs": [ - "Create a new contract.", - "", - "The caller will be admin of the contract." - ], - "label": "new", - "payable": false, - "selector": "0x9bae9d5e" - } - ], - "docs": [], - "events": [ - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "owner_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " A bucket was created. The given account is its first owner and payer of resources." - ], - "label": "BucketCreated" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": false, - "label": "resource", - "type": { - "displayName": [ - "Resource" - ], - "type": 9 - } - } - ], - "docs": [ - " Some amount of resources of a cluster were allocated to a bucket." - ], - "label": "BucketAllocated" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - } - ], - "docs": [ - " The due costs of a bucket was settled from the bucket payer to the cluster." - ], - "label": "BucketSettlePayment" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "public_availability", - "type": { - "displayName": [ - "bool" - ], - "type": 3 - } - } - ], - "docs": [ - " The availiablity of the bucket was updated." - ], - "label": "BucketAvailabilityUpdated" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "manager", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "docs": [], - "indexed": false, - "label": "cluster_params", - "type": { - "displayName": [ - "ClusterParams" - ], - "type": 16 - } - } - ], - "docs": [ - " A new cluster was created." - ], - "label": "ClusterCreated" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - } - ], - "docs": [ - " A vnode was re-assigned to new node." - ], - "label": "ClusterNodeReplaced" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": false, - "label": "resource", - "type": { - "displayName": [ - "Resource" - ], - "type": 9 - } - } - ], - "docs": [ - " Some resources were reserved for the cluster from the nodes." - ], - "label": "ClusterReserveResource" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "provider_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " The share of revenues of a cluster for a provider was distributed." - ], - "label": "ClusterDistributeRevenues" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "manager", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " A new cluster was created." - ], - "label": "CdnClusterCreated" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "provider_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " The respective share of revenues of a CDN cluster for a provider was distributed." - ], - "label": "CdnClusterDistributeRevenues" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "provider_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "docs": [], - "indexed": false, - "label": "undistributed_payment", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - } - ], - "docs": [ - " A node was created. The given account is its owner and recipient of revenues." - ], - "label": "CdnNodeCreated" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - }, - { - "docs": [], - "indexed": true, - "label": "provider_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "docs": [], - "indexed": false, - "label": "rent_per_month", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - }, - { - "docs": [], - "indexed": false, - "label": "node_params", - "type": { - "displayName": [ - "NodeParams" - ], - "type": 16 - } - } - ], - "docs": [ - " A node was created. The given account is its owner and recipient of revenues." - ], - "label": "NodeCreated" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "account_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "docs": [], - "indexed": false, - "label": "value", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - } - ], - "docs": [ - " Tokens were deposited on an account." - ], - "label": "Deposit" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "account_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "docs": [], - "indexed": false, - "label": "permission", - "type": { - "displayName": [ - "Permission" - ], - "type": 77 - } - } - ], - "docs": [ - " A permission was granted to the account." - ], - "label": "GrantPermission" - }, - { - "args": [ - { - "docs": [], - "indexed": true, - "label": "account_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "docs": [], - "indexed": false, - "label": "permission", - "type": { - "displayName": [ - "Permission" - ], - "type": 77 - } - } - ], - "docs": [ - " A permission was revoked from the account." - ], - "label": "RevokePermission" - } - ], - "messages": [ - { - "args": [ - { - "label": "bucket_params", - "type": { - "displayName": [ - "BucketParams" - ], - "type": 16 - } - }, - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "owner_id", - "type": { - "displayName": [ - "Option" - ], - "type": 43 - } - } - ], - "docs": [ - " Create a new bucket and return its `bucket_id`.", - "", - " The caller will be its first owner and payer of resources.", - "", - " `bucket_params` is configuration used by clients and nodes. See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema)", - "", - " The bucket can be connected to a single cluster (currently). Allocate cluster resources with the function `bucket_alloc_into_cluster`" - ], - "label": "bucket_create", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [ - "BucketId" - ], - "type": 9 - }, - "selector": "0x0aeb2379" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "owner_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Change owner of the bucket", - "", - " Provide the account of new owner" - ], - "label": "bucket_change_owner", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xc7d0c2cd" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "resource", - "type": { - "displayName": [ - "Resource" - ], - "type": 9 - } - } - ], - "docs": [ - " Allocate some resources of a cluster to a bucket.", - "", - " The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes)." - ], - "label": "bucket_alloc_into_cluster", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x4c482d19" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - } - ], - "docs": [ - " Settle the due costs of a bucket from its payer account to the cluster account." - ], - "label": "bucket_settle_payment", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0x15974555" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "params", - "type": { - "displayName": [ - "BucketParams" - ], - "type": 16 - } - } - ], - "docs": [ - " Change the `bucket_params`, which is configuration used by clients and nodes.", - "", - " See the [data structure of BucketParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "bucket_change_params", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x9f2d075b" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - } - ], - "docs": [ - " Get the current status of a bucket." - ], - "label": "bucket_get", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 45 - }, - "selector": "0x3802cb77" - }, - { - "args": [ - { - "label": "offset", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "limit", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "filter_owner_id", - "type": { - "displayName": [ - "Option" - ], - "type": 43 - } - } - ], - "docs": [ - " Iterate through all buckets.", - "", - " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", - " The optimal `limit` depends on the size of params.", - "", - " The results can be filtered by owner. Note that paging must still be completed fully." - ], - "label": "bucket_list", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [], - "type": 49 - }, - "selector": "0x417ab584" - }, - { - "args": [ - { - "label": "owner_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Iterate through all buckets and return only those owned by owner", - "", - " This method returns bucket struct, not the status" - ], - "label": "bucket_list_for_account", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Vec" - ], - "type": 6 - }, - "selector": "0xc434cf57" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "public_availability", - "type": { - "displayName": [ - "bool" - ], - "type": 3 - } - } - ], - "docs": [ - " Set availiablity of the bucket" - ], - "label": "bucket_set_availability", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x053eb3ce" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "new_resource_cap", - "type": { - "displayName": [ - "Resource" - ], - "type": 9 - } - } - ], - "docs": [ - " Set max resource cap to be charged by CDN for public bucket" - ], - "label": "bucket_set_resource_cap", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x85010c6d" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - } - ], - "docs": [ - " Set permission for the reader of the bucket" - ], - "label": "get_bucket_writers", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [ - "Vec" - ], - "type": 14 - }, - "selector": "0x499cd4b7" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "writer", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Set permission for the writer of the bucket" - ], - "label": "bucket_set_writer_perm", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xea2e477a" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "writer", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Revoke permission for the writer of the bucket" - ], - "label": "bucket_revoke_writer_perm", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x2b3d8dd1" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - } - ], - "docs": [ - " Set permission for the reader of the bucket" - ], - "label": "get_bucket_readers", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [ - "Vec" - ], - "type": 14 - }, - "selector": "0xb9a7cc1c" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "reader", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Set permission for the reader of the bucket" - ], - "label": "bucket_set_reader_perm", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xfc0e94ea" - }, - { - "args": [ - { - "label": "bucket_id", - "type": { - "displayName": [ - "BucketId" - ], - "type": 9 - } - }, - { - "label": "writer", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Revoke permission for the reader of the bucket" - ], - "label": "bucket_revoke_reader_perm", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xe9bfed5a" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "node_ids", - "type": { - "displayName": [ - "Vec" - ], - "type": 20 - } - }, - { - "label": "v_nodes", - "type": { - "displayName": [ - "Vec" - ], - "type": 21 - } - } - ], - "docs": [ - " Removes a node to an existing cluster", - "", - " The caller will be its first manager." - ], - "label": "cluster_remove_node", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x793e0778" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "node_ids", - "type": { - "displayName": [ - "Vec" - ], - "type": 20 - } - }, - { - "label": "v_nodes", - "type": { - "displayName": [ - "Vec" - ], - "type": 21 - } - } - ], - "docs": [ - " Adds node to an existing cluster", - "", - " The caller will be its first manager." - ], - "label": "cluster_add_node", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0xf7496bdc" - }, - { - "args": [ - { - "label": "_unused", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "label": "v_nodes", - "type": { - "displayName": [ - "Vec" - ], - "type": 21 - } - }, - { - "label": "node_ids", - "type": { - "displayName": [ - "Vec" - ], - "type": 20 - } - }, - { - "label": "cluster_params", - "type": { - "displayName": [ - "ClusterParams" - ], - "type": 16 - } - } - ], - "docs": [ - " Create a new cluster and return its `cluster_id`.", - "", - " The caller will be its first manager.", - "", - " The cluster is split in a number of vnodes. The vnodes are assigned to the given physical nodes in a round-robin. Only nodes of providers that trust the cluster manager can be used (see `node_trust_manager`). The assignment can be changed with the function `cluster_replace_node`.", - "", - " `cluster_params` is configuration used by clients and nodes. In particular, this describes the semantics of vnodes. See the [data structure of ClusterParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "cluster_create", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [ - "ClusterId" - ], - "type": 9 - }, - "selector": "0x4c0f21f6" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "amount", - "type": { - "displayName": [ - "Resource" - ], - "type": 9 - } - } - ], - "docs": [ - " As manager, reserve more resources for the cluster from the free capacity of nodes.", - "", - " The amount of resources is given per vnode (total resources will be `resource` times the number of vnodes)." - ], - "label": "cluster_reserve_resource", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xb5e38125" - }, - { - "args": [ - { - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - }, - { - "label": "new_tag", - "type": { - "displayName": [ - "NodeTag" - ], - "type": 31 - } - } - ], - "docs": [ - " As manager, change a node tag" - ], - "label": "cluster_change_node_tag", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x9640d48e" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "v_nodes", - "type": { - "displayName": [ - "Vec" - ], - "type": 22 - } - }, - { - "label": "new_node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - } - ], - "docs": [ - " As manager, re-assign a vnode to another physical node.", - "", - " The cluster manager can only use nodes of providers that trust him (see `node_trust_manager`), or any nodes if he is also SuperAdmin." - ], - "label": "cluster_replace_node", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x48194ab1" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - } - ], - "docs": [ - " Trigger the distribution of revenues from the cluster to the providers." - ], - "label": "cluster_distribute_revenues", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0xe71e66fc" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "params", - "type": { - "displayName": [ - "ClusterParams" - ], - "type": 16 - } - } - ], - "docs": [ - " Change the `cluster_params`, which is configuration used by clients and nodes.", - "", - " See the [data structure of ClusterParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "cluster_change_params", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x1207912c" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - } - ], - "docs": [ - " Get the current status of a cluster." - ], - "label": "cluster_get", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 51 - }, - "selector": "0xe75411f5" - }, - { - "args": [ - { - "label": "offset", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "limit", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "filter_manager_id", - "type": { - "displayName": [ - "Option" - ], - "type": 43 - } - } - ], - "docs": [ - " Iterate through all clusters.", - "", - " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", - " The optimal `limit` depends on the size of params.", - "", - " The results can be filtered by manager. Note that paging must still be completed fully." - ], - "label": "cluster_list", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [], - "type": 53 - }, - "selector": "0xd9db9d44" - }, - { - "args": [ - { - "label": "cdn_node_ids", - "type": { - "displayName": [ - "Vec" - ], - "type": 20 - } - } - ], - "docs": [ - " Create a new cluster and return its `cluster_id`.", - "", - " The caller will be its first manager.", - "", - " The CDN node ids are provided, which will form a cluster." - ], - "label": "cdn_cluster_create", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [ - "ClusterId" - ], - "type": 9 - }, - "selector": "0x4344cd7e" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "usd_per_gb", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - } - ], - "docs": [ - " Set rate for streaming (price per gb)" - ], - "label": "cdn_set_rate", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x7578922a" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - } - ], - "docs": [ - " Get rate for streaming (price per gb)" - ], - "label": "cdn_get_rate", - "mutates": false, - "payable": true, - "returnType": { - "displayName": [ - "Balance" - ], - "type": 12 - }, - "selector": "0xa1e3ea8a" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - }, - { - "label": "aggregates_accounts", - "type": { - "displayName": [ - "Vec" - ], - "type": 55 - } - }, - { - "label": "aggregates_nodes", - "type": { - "displayName": [ - "Vec" - ], - "type": 57 - } - }, - { - "label": "aggregates_buckets", - "type": { - "displayName": [ - "Vec" - ], - "type": 59 - } - }, - { - "label": "era", - "type": { - "displayName": [ - "u64" - ], - "type": 23 - } - } - ], - "docs": [ - " As validator, charge payments from users and allocate undistributed payments to CDN nodes.", - "", - " As a result CDN cluster revenue increases, which can be distributed between CDN node providers via method cdn_cluster_distribute_revenues." - ], - "label": "cdn_cluster_put_revenue", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x7219be3f" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - } - ], - "docs": [ - " Trigger the distribution of revenues from the cluster to the CDN node providers.", - "", - " Anyone can call this method.", - "", - " Undistributed payments will be trasnferred, CDN cluster revenue will decrease." - ], - "label": "cdn_cluster_distribute_revenues", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0xfa8d570d" - }, - { - "args": [ - { - "label": "cluster_id", - "type": { - "displayName": [ - "ClusterId" - ], - "type": 9 - } - } - ], - "docs": [ - " Get the current status of a cluster." - ], - "label": "cdn_cluster_get", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 61 - }, - "selector": "0x4b22fbf1" - }, - { - "args": [ - { - "label": "offset", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "limit", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "filter_manager_id", - "type": { - "displayName": [ - "Option" - ], - "type": 43 - } - } - ], - "docs": [ - " Iterate through all clusters.", - "", - " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", - " The optimal `limit` depends on the size of params.", - "", - " The results can be filtered by manager. Note that paging must still be completed fully." - ], - "label": "cdn_cluster_list", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [], - "type": 63 - }, - "selector": "0xb242a64f" - }, - { - "args": [ - { - "label": "cdn_owner", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - }, - { - "label": "commit", - "type": { - "displayName": [ - "Commit" - ], - "type": 37 - } - } - ], - "docs": [ - " CDN node operator sets the commit for current era." - ], - "label": "set_commit", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0xe445e1fd" - }, - { - "args": [ - { - "label": "cdn_owner", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Return the last commit submitted by CDN node operator" - ], - "label": "get_commit", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Vec" - ], - "type": 35 - }, - "selector": "0x5329f551" - }, - { - "args": [ - { - "label": "node", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - } - ], - "docs": [ - " Return last era validated per CDN node" - ], - "label": "get_validated_commit", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "EraAndTimestamp" - ], - "type": 40 - }, - "selector": "0x7d497bc1" - }, - { - "args": [ - { - "label": "era_config", - "type": { - "displayName": [ - "EraConfig" - ], - "type": 65 - } - } - ], - "docs": [ - " Set the new configs for era" - ], - "label": "set_era", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x49a5b8f7" - }, - { - "args": [], - "docs": [ - " Return current status of an era" - ], - "label": "get_era", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "EraStatus" - ], - "type": 66 - }, - "selector": "0x617f696b" - }, - { - "args": [], - "docs": [ - " Return current era settings" - ], - "label": "get_era_settings", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "EraConfig" - ], - "type": 65 - }, - "selector": "0x84b61468" - }, - { - "args": [ - { - "label": "manager", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " As node provider, authorize a cluster manager to use his nodes." - ], - "label": "cdn_node_trust_manager", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x372daa96" - }, - { - "args": [ - { - "label": "manager", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " As node provider, revoke the authorization of a cluster manager to use his nodes." - ], - "label": "cdn_node_distrust_manager", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0xf67f5438" - }, - { - "args": [ - { - "label": "node_params", - "type": { - "displayName": [ - "Params" - ], - "type": 16 - } - } - ], - "docs": [ - " Create a new node and return its `node_id`.", - "", - " The caller will be its owner.", - "", - " `node_params` is configuration used by clients and nodes. In particular, this contains the URL to the service. See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "cdn_node_create", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [ - "NodeId" - ], - "type": 9 - }, - "selector": "0xe8aa4ade" - }, - { - "args": [ - { - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - }, - { - "label": "params", - "type": { - "displayName": [ - "NodeParams" - ], - "type": 16 - } - } - ], - "docs": [ - " Change the `node_params`, which is configuration used by clients and nodes.", - "", - " See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "cdn_node_change_params", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0xf52c20f5" - }, - { - "args": [ - { - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - } - ], - "docs": [ - " Get the current state of the cdn node" - ], - "label": "cdn_node_get", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 68 - }, - "selector": "0xf9a5a813" - }, - { - "args": [ - { - "label": "offset", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "limit", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "filter_provider_id", - "type": { - "displayName": [ - "Option" - ], - "type": 43 - } - } - ], - "docs": [ - " Iterate through all nodes.", - "", - " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", - " The optimal `limit` depends on the size of params.", - "", - " The results can be filtered by owner. Note that paging must still be completed fully." - ], - "label": "cdn_node_list", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [], - "type": 70 - }, - "selector": "0xf8589aae" - }, - { - "args": [ - { - "label": "manager", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " As node provider, authorize a cluster manager to use his nodes." - ], - "label": "node_trust_manager", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x6fd54a01" - }, - { - "args": [ - { - "label": "manager", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " As node provider, revoke the authorization of a cluster manager to use his nodes." - ], - "label": "node_distrust_manager", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0x40912279" - }, - { - "args": [ - { - "label": "rent_per_month", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - }, - { - "label": "node_params", - "type": { - "displayName": [ - "NodeParams" - ], - "type": 16 - } - }, - { - "label": "capacity", - "type": { - "displayName": [ - "Resource" - ], - "type": 9 - } - }, - { - "label": "node_tag", - "type": { - "displayName": [ - "NodeTag" - ], - "type": 31 - } - }, - { - "label": "pubkey", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Create a new node and return its `node_id`.", - "", - " The caller will be its owner.", - "", - " `node_params` is configuration used by clients and nodes. In particular, this contains the URL to the service. See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "node_create", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [ - "NodeId" - ], - "type": 9 - }, - "selector": "0xb77ac1bb" - }, - { - "args": [ - { - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - }, - { - "label": "params", - "type": { - "displayName": [ - "NodeParams" - ], - "type": 16 - } - } - ], - "docs": [ - " Change the `node_params`, which is configuration used by clients and nodes.", - "", - " See the [data structure of NodeParams](https://docs.cere.network/ddc/protocols/contract-params-schema)" - ], - "label": "node_change_params", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0x258ccb2a" - }, - { - "args": [ - { - "label": "node_id", - "type": { - "displayName": [ - "NodeId" - ], - "type": 9 - } - } - ], - "docs": [ - " Get the current status of a node." - ], - "label": "node_get", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 72 - }, - "selector": "0x847f3997" - }, - { - "args": [ - { - "label": "pubkey", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Get the current status of a node by a public key." - ], - "label": "node_get_by_pubkey", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 72 - }, - "selector": "0x7f6c82d4" - }, - { - "args": [ - { - "label": "offset", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "limit", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - }, - { - "label": "filter_provider_id", - "type": { - "displayName": [ - "Option" - ], - "type": 43 - } - } - ], - "docs": [ - " Iterate through all nodes.", - "", - " The algorithm for paging is: start with `offset = 1` and `limit = 20`. The function returns a `(results, max_id)`. Call again with `offset += limit`, until `offset >= max_id`.", - " The optimal `limit` depends on the size of params.", - "", - " The results can be filtered by owner. Note that paging must still be completed fully." - ], - "label": "node_list", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [], - "type": 74 - }, - "selector": "0x423286d6" - }, - { - "args": [], - "docs": [ - " Get the Fee Percentage Basis Points that will be charged by the protocol" - ], - "label": "get_fee_bp", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "u32" - ], - "type": 9 - }, - "selector": "0x0d5daf5f" - }, - { - "args": [ - { - "label": "fee_bp", - "type": { - "displayName": [ - "u32" - ], - "type": 9 - } - } - ], - "docs": [ - " Return the last commit submitted by CDN node operator" - ], - "label": "set_fee_bp", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xc5e3e2ca" - }, - { - "args": [], - "docs": [ - " Return fees accumulated by the protocol" - ], - "label": "get_protocol_revenues", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Cash" - ], - "type": 19 - }, - "selector": "0x07c63885" - }, - { - "args": [ - { - "label": "amount", - "type": { - "displayName": [ - "u128" - ], - "type": 12 - } - } - ], - "docs": [ - " Pay the revenues accumulated by the protocol" - ], - "label": "protocol_withdraw_revenues", - "mutates": true, - "payable": false, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x85c6fa6d" - }, - { - "args": [], - "docs": [ - " As user, deposit tokens on the account of the caller from the transaction value. This deposit", - " can be used to pay for the services to buckets of the account." - ], - "label": "account_deposit", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xc311af62" - }, - { - "args": [ - { - "label": "bond_amount", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - } - ], - "docs": [ - " As user, bond some amount of tokens from the withdrawable balance. These funds will be used to pay for CDN node service." - ], - "label": "account_bond", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xe9fad0bf" - }, - { - "args": [ - { - "label": "amount_to_unbond", - "type": { - "displayName": [ - "Cash" - ], - "type": 19 - } - } - ], - "docs": [ - " As user, unbond a specified amount of tokens. The tokens will be locked for some time, as defined by contract owner." - ], - "label": "account_unbond", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0xf7ea2c67" - }, - { - "args": [], - "docs": [ - " As user, move the unbonded tokens back to withdrawable balance state.", - "", - " This can be triggered after unbonded_timestamp" - ], - "label": "account_withdraw_unbonded", - "mutates": true, - "payable": true, - "returnType": { - "displayName": [], - "type": 44 - }, - "selector": "0x98173716" - }, - { - "args": [ - { - "label": "account_id", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - } - ], - "docs": [ - " Get the current status of an account." - ], - "label": "account_get", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Result" - ], - "type": 76 - }, - "selector": "0x1d4220fa" - }, - { - "args": [], - "docs": [ - " Get the current conversion rate between the native currency and an external currency (USD)." - ], - "label": "account_get_usd_per_cere", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "Balance" - ], - "type": 12 - }, - "selector": "0xe4a4652a" - }, - { - "args": [ - { - "label": "usd_per_cere", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - } - ], - "docs": [ - " As price oracle, set the current conversion rate between the native currency and an external currency (USD).", - "", - " This requires the permission SetExchangeRate or SuperAdmin." - ], - "label": "account_set_usd_per_cere", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0x48d45ee8" - }, - { - "args": [ - { - "label": "grantee", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "label": "permission", - "type": { - "displayName": [ - "Permission" - ], - "type": 77 - } - } - ], - "docs": [ - " Check whether the given account has the given permission currently,", - " or the SuperAdmin permission." - ], - "label": "has_permission", - "mutates": false, - "payable": false, - "returnType": { - "displayName": [ - "bool" - ], - "type": 3 - }, - "selector": "0xe0942492" - }, - { - "args": [ - { - "label": "grantee", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "label": "permission", - "type": { - "displayName": [ - "Permission" - ], - "type": 77 - } - } - ], - "docs": [ - " As SuperAdmin, grant any permission to any account." - ], - "label": "admin_grant_permission", - "mutates": true, - "payable": true, - "returnType": null, - "selector": "0xbe41ea55" - }, - { - "args": [ - { - "label": "grantee", - "type": { - "displayName": [ - "AccountId" - ], - "type": 8 - } - }, - { - "label": "permission", - "type": { - "displayName": [ - "Permission" - ], - "type": 77 - } - } - ], - "docs": [ - " As SuperAdmin, revoke any permission to any account." - ], - "label": "admin_revoke_permission", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0x6b150666" - }, - { - "args": [ - { - "label": "amount", - "type": { - "displayName": [ - "Balance" - ], - "type": 12 - } - } - ], - "docs": [ - " As SuperAdmin, withdraw the funds held in custody in this contract.", - "", - " This is a temporary measure to allow migrating the funds to a new version of the contract." - ], - "label": "admin_withdraw", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0x2f6e0868" - }, - { - "args": [ - { - "label": "config", - "type": { - "displayName": [ - "FeeConfig" - ], - "type": 78 - } - } - ], - "docs": [ - " As SuperAdmin, set the network and cluster fee configuration." - ], - "label": "admin_set_fee_config", - "mutates": true, - "payable": false, - "returnType": null, - "selector": "0x00d441e7" - }, - { - "args": [], - "docs": [ - " Get all Account IDs stored in the SC" - ], - "label": "get_accounts", - "mutates": false, - "payable": true, - "returnType": { - "displayName": [ - "Vec" - ], - "type": 14 - }, - "selector": "0xef03ead7" - } - ] - }, - "storage": { - "struct": { - "fields": [ - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0000000000000000000000000000000000000000000000000000000000000000", - "ty": 0 - } - }, - "name": null - } - ] - } - }, - "name": "perms" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0100000000000000000000000000000000000000000000000000000000000000", - "ty": 6 - } - }, - "name": null - } - ] - } - }, - "name": "buckets" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0200000000000000000000000000000000000000000000000000000000000000", - "ty": 13 - } - }, - "name": "writers" - }, - { - "layout": { - "cell": { - "key": "0x0300000000000000000000000000000000000000000000000000000000000000", - "ty": 13 - } - }, - "name": "readers" - } - ] - } - }, - "name": "buckets_perms" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0400000000000000000000000000000000000000000000000000000000000000", - "ty": 15 - } - }, - "name": null - } - ] - } - }, - "name": "bucket_params" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0500000000000000000000000000000000000000000000000000000000000000", - "ty": 17 - } - }, - "name": null - } - ] - } - }, - "name": "clusters" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0600000000000000000000000000000000000000000000000000000000000000", - "ty": 24 - } - }, - "name": null - } - ] - } - }, - "name": "cdn_clusters" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0700000000000000000000000000000000000000000000000000000000000000", - "ty": 15 - } - }, - "name": null - } - ] - } - }, - "name": "cluster_params" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0800000000000000000000000000000000000000000000000000000000000000", - "ty": 26 - } - }, - "name": null - } - ] - } - }, - "name": "cdn_nodes" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0900000000000000000000000000000000000000000000000000000000000000", - "ty": 15 - } - }, - "name": null - } - ] - } - }, - "name": "cdn_node_params" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0a00000000000000000000000000000000000000000000000000000000000000", - "ty": 28 - } - }, - "name": "account_node" - }, - { - "layout": { - "cell": { - "key": "0x0b00000000000000000000000000000000000000000000000000000000000000", - "ty": 29 - } - }, - "name": "nodes" - } - ] - } - }, - "name": "nodes" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0c00000000000000000000000000000000000000000000000000000000000000", - "ty": 15 - } - }, - "name": null - } - ] - } - }, - "name": "node_params" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0d00000000000000000000000000000000000000000000000000000000000000", - "ty": 32 - } - }, - "name": null - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x0e00000000000000000000000000000000000000000000000000000000000000", - "ty": 12 - } - }, - "name": null - } - ] - } - }, - "name": null - }, - { - "layout": { - "cell": { - "key": "0x0f00000000000000000000000000000000000000000000000000000000000000", - "ty": 14 - } - }, - "name": null - } - ] - } - }, - "name": "accounts" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x1000000000000000000000000000000000000000000000000000000000000000", - "ty": 12 - } - }, - "name": "network_fee_bp" - }, - { - "layout": { - "cell": { - "key": "0x1100000000000000000000000000000000000000000000000000000000000000", - "ty": 8 - } - }, - "name": "network_fee_destination" - }, - { - "layout": { - "cell": { - "key": "0x1200000000000000000000000000000000000000000000000000000000000000", - "ty": 12 - } - }, - "name": "cluster_management_fee_bp" - } - ] - } - }, - "name": null - } - ] - } - }, - "name": "network_fee" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x1300000000000000000000000000000000000000000000000000000000000000", - "ty": 8 - } - }, - "name": "operator_id" - }, - { - "layout": { - "cell": { - "key": "0x1400000000000000000000000000000000000000000000000000000000000000", - "ty": 34 - } - }, - "name": "commits" - }, - { - "layout": { - "cell": { - "key": "0x1500000000000000000000000000000000000000000000000000000000000000", - "ty": 39 - } - }, - "name": "validated_commits" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x1600000000000000000000000000000000000000000000000000000000000000", - "ty": 23 - } - }, - "name": "start" - }, - { - "layout": { - "cell": { - "key": "0x1700000000000000000000000000000000000000000000000000000000000000", - "ty": 23 - } - }, - "name": "interval" - }, - { - "layout": { - "cell": { - "key": "0x1800000000000000000000000000000000000000000000000000000000000000", - "ty": 23 - } - }, - "name": "commit_duration" - }, - { - "layout": { - "cell": { - "key": "0x1900000000000000000000000000000000000000000000000000000000000000", - "ty": 23 - } - }, - "name": "validation_duration" - } - ] - } - }, - "name": "era_settings" - } - ] - } - }, - "name": "committer_store" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x1a00000000000000000000000000000000000000000000000000000000000000", - "ty": 8 - } - }, - "name": "admin" - }, - { - "layout": { - "cell": { - "key": "0x1b00000000000000000000000000000000000000000000000000000000000000", - "ty": 9 - } - }, - "name": "fee_bp" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x1c00000000000000000000000000000000000000000000000000000000000000", - "ty": 12 - } - }, - "name": null - } - ] - } - }, - "name": "revenues" - } - ] - } - }, - "name": "protocol_store" - }, - { - "layout": { - "struct": { - "fields": [ - { - "layout": { - "cell": { - "key": "0x1d00000000000000000000000000000000000000000000000000000000000000", - "ty": 41 - } - }, - "name": null - } - ] - } - }, - "name": "topology_store" - } - ] - } - }, - "types": [ - { - "id": 0, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 4, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 1 - }, - { - "name": "V", - "type": 3 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 1, - "type": { - "def": { - "sequence": { - "type": 2 - } - } - } - }, - { - "id": 2, - "type": { - "def": { - "primitive": "u8" - } - } - }, - { - "id": 3, - "type": { - "def": { - "primitive": "bool" - } - } - }, - { - "id": 4, - "type": { - "def": { - "composite": { - "fields": [ - { - "type": 5, - "typeName": "[u8; 32]" - } - ] - } - }, - "path": [ - "ink_primitives", - "Key" - ] - } - }, - { - "id": 5, - "type": { - "def": { - "array": { - "len": 32, - "type": 2 - } - } - } - }, - { - "id": 6, - "type": { - "def": { - "sequence": { - "type": 7 - } - } - } - }, - { - "id": 7, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "owner_id", - "type": 8, - "typeName": "AccountId" - }, - { - "name": "cluster_id", - "type": 9, - "typeName": "ClusterId" - }, - { - "name": "flow", - "type": 10, - "typeName": "Flow" - }, - { - "name": "resource_reserved", - "type": 9, - "typeName": "Resource" - }, - { - "name": "public_availability", - "type": 3, - "typeName": "bool" - }, - { - "name": "resource_consumption_cap", - "type": 9, - "typeName": "Resource" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "bucket", - "entity", - "Bucket" - ] - } - }, - { - "id": 8, - "type": { - "def": { - "composite": { - "fields": [ - { - "type": 5, - "typeName": "[u8; 32]" - } - ] - } - }, - "path": [ - "ink_env", - "types", - "AccountId" - ] - } - }, - { - "id": 9, - "type": { - "def": { - "primitive": "u32" - } - } - }, - { - "id": 10, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "from", - "type": 8, - "typeName": "AccountId" - }, - { - "name": "schedule", - "type": 11, - "typeName": "Schedule" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "flow", - "Flow" - ] - } - }, - { - "id": 11, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "rate", - "type": 12, - "typeName": "Balance" - }, - { - "name": "offset", - "type": 12, - "typeName": "Balance" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "schedule", - "Schedule" - ] - } - }, - { - "id": 12, - "type": { - "def": { - "primitive": "u128" - } - } - }, - { - "id": 13, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 4, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 9 - }, - { - "name": "V", - "type": 14 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 14, - "type": { - "def": { - "sequence": { - "type": 8 - } - } - } - }, - { - "id": 15, - "type": { - "def": { - "sequence": { - "type": 16 - } - } - } - }, - { - "id": 16, - "type": { - "def": { - "primitive": "str" - } - } - }, - { - "id": 17, - "type": { - "def": { - "sequence": { - "type": 18 - } - } - } - }, - { - "id": 18, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "manager_id", - "type": 8, - "typeName": "AccountId" - }, - { - "name": "resource_per_vnode", - "type": 9, - "typeName": "Resource" - }, - { - "name": "resource_used", - "type": 9, - "typeName": "Resource" - }, - { - "name": "revenues", - "type": 19, - "typeName": "Cash" - }, - { - "name": "node_ids", - "type": 20, - "typeName": "Vec" - }, - { - "name": "v_nodes", - "type": 21, - "typeName": "Vec>" - }, - { - "name": "total_rent", - "type": 12, - "typeName": "Balance" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cluster", - "entity", - "Cluster" - ] - } - }, - { - "id": 19, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "value", - "type": 12, - "typeName": "Balance" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cash", - "Cash" - ] - } - }, - { - "id": 20, - "type": { - "def": { - "sequence": { - "type": 9 - } - } - } - }, - { - "id": 21, - "type": { - "def": { - "sequence": { - "type": 22 - } - } - } - }, - { - "id": 22, - "type": { - "def": { - "sequence": { - "type": 23 - } - } - } - }, - { - "id": 23, - "type": { - "def": { - "primitive": "u64" - } - } - }, - { - "id": 24, - "type": { - "def": { - "sequence": { - "type": 25 - } - } - } - }, - { - "id": 25, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "manager_id", - "type": 8, - "typeName": "AccountId" - }, - { - "name": "cdn_nodes", - "type": 20, - "typeName": "Vec" - }, - { - "name": "resources_used", - "type": 9, - "typeName": "Resource" - }, - { - "name": "revenues", - "type": 19, - "typeName": "Cash" - }, - { - "name": "usd_per_gb", - "type": 12, - "typeName": "Balance" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cdn_cluster", - "entity", - "CdnCluster" - ] - } - }, - { - "id": 26, - "type": { - "def": { - "sequence": { - "type": 27 - } - } - } - }, - { - "id": 27, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "provider_id", - "type": 8, - "typeName": "ProviderId" - }, - { - "name": "undistributed_payment", - "type": 12, - "typeName": "Balance" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cdn_node", - "entity", - "CdnNode" - ] - } - }, - { - "id": 28, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 4, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 8 - }, - { - "name": "V", - "type": 9 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 29, - "type": { - "def": { - "sequence": { - "type": 30 - } - } - } - }, - { - "id": 30, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "provider_id", - "type": 8, - "typeName": "ProviderId" - }, - { - "name": "rent_per_month", - "type": 12, - "typeName": "Balance" - }, - { - "name": "free_resource", - "type": 9, - "typeName": "Resource" - }, - { - "name": "node_tag", - "type": 31, - "typeName": "NodeTag" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "node", - "entity", - "Node" - ] - } - }, - { - "id": 31, - "type": { - "def": { - "variant": { - "variants": [ - { - "index": 0, - "name": "UNKNOWN" - }, - { - "index": 1, - "name": "ACTIVE" - }, - { - "index": 2, - "name": "ADDING" - }, - { - "index": 3, - "name": "DELETING" - }, - { - "index": 4, - "name": "OFFLINE" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "node", - "entity", - "NodeTag" - ] - } - }, - { - "id": 32, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 4, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 8 - }, - { - "name": "V", - "type": 33 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 33, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "deposit", - "type": 19, - "typeName": "Cash" - }, - { - "name": "bonded", - "type": 19, - "typeName": "Cash" - }, - { - "name": "negative", - "type": 19, - "typeName": "Cash" - }, - { - "name": "unbonded_amount", - "type": 19, - "typeName": "Cash" - }, - { - "name": "unbonded_timestamp", - "type": 23, - "typeName": "u64" - }, - { - "name": "payable_schedule", - "type": 11, - "typeName": "Schedule" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "account", - "entity", - "Account" - ] - } - }, - { - "id": 34, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 4, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 8 - }, - { - "name": "V", - "type": 35 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 35, - "type": { - "def": { - "sequence": { - "type": 36 - } - } - } - }, - { - "id": 36, - "type": { - "def": { - "tuple": [ - 9, - 37 - ] - } - } - }, - { - "id": 37, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "hash", - "type": 38, - "typeName": "Hash" - }, - { - "name": "total_logs", - "type": 12, - "typeName": "u128" - }, - { - "name": "from_timestamp", - "type": 23, - "typeName": "u64" - }, - { - "name": "to_timestamp", - "type": 23, - "typeName": "u64" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "committer", - "store", - "Commit" - ] - } - }, - { - "id": 38, - "type": { - "def": { - "composite": { - "fields": [ - { - "type": 5, - "typeName": "[u8; 32]" - } - ] - } - }, - "path": [ - "ink_env", - "types", - "Hash" - ] - } - }, - { - "id": 39, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 4, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 9 - }, - { - "name": "V", - "type": 40 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 40, - "type": { - "def": { - "tuple": [ - 23, - 23 - ] - } - } - }, - { - "id": 41, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "offset_key", - "type": 4, - "typeName": "Key" - } - ] - } - }, - "params": [ - { - "name": "K", - "type": 42 - }, - { - "name": "V", - "type": 9 - } - ], - "path": [ - "ink_storage", - "lazy", - "mapping", - "Mapping" - ] - } - }, - { - "id": 42, - "type": { - "def": { - "tuple": [ - 9, - 23 - ] - } - } - }, - { - "id": 43, - "type": { - "def": { - "variant": { - "variants": [ - { - "index": 0, - "name": "None" - }, - { - "fields": [ - { - "type": 8 - } - ], - "index": 1, - "name": "Some" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 8 - } - ], - "path": [ - "Option" - ] - } - }, - { - "id": 44, - "type": { - "def": { - "tuple": [] - } - } - }, - { - "id": 45, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 46 - } - ], - "index": 0, - "name": "Ok" - }, - { - "fields": [ - { - "type": 48 - } - ], - "index": 1, - "name": "Err" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 46 - }, - { - "name": "E", - "type": 48 - } - ], - "path": [ - "Result" - ] - } - }, - { - "id": 46, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "bucket_id", - "type": 9, - "typeName": "BucketId" - }, - { - "name": "bucket", - "type": 47, - "typeName": "BucketInStatus" - }, - { - "name": "params", - "type": 16, - "typeName": "BucketParams" - }, - { - "name": "writer_ids", - "type": 14, - "typeName": "Vec" - }, - { - "name": "reader_ids", - "type": 14, - "typeName": "Vec" - }, - { - "name": "rent_covered_until_ms", - "type": 23, - "typeName": "u64" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "bucket", - "entity", - "BucketStatus" - ] - } - }, - { - "id": 47, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "owner_id", - "type": 8, - "typeName": "AccountId" - }, - { - "name": "cluster_id", - "type": 9, - "typeName": "ClusterId" - }, - { - "name": "resource_reserved", - "type": 9, - "typeName": "Resource" - }, - { - "name": "public_availability", - "type": 3, - "typeName": "bool" - }, - { - "name": "resource_consumption_cap", - "type": 9, - "typeName": "Resource" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "bucket", - "entity", - "BucketInStatus" - ] - } - }, - { - "id": 48, - "type": { - "def": { - "variant": { - "variants": [ - { - "index": 0, - "name": "BucketDoesNotExist" - }, - { - "index": 1, - "name": "ClusterDoesNotExist" - }, - { - "index": 2, - "name": "ParamsTooBig" - }, - { - "index": 3, - "name": "VNodeDoesNotExist" - }, - { - "index": 4, - "name": "BondingPeriodNotFinished" - }, - { - "index": 5, - "name": "BucketClusterAlreadyConnected" - }, - { - "index": 6, - "name": "BucketClusterNotSetup" - }, - { - "index": 7, - "name": "NodeDoesNotExist" - }, - { - "index": 8, - "name": "NodeAlreadyExists" - }, - { - "index": 9, - "name": "FlowDoesNotExist" - }, - { - "index": 10, - "name": "AccountDoesNotExist" - }, - { - "index": 11, - "name": "ParamsDoesNotExist" - }, - { - "index": 12, - "name": "UnauthorizedProvider" - }, - { - "index": 13, - "name": "UnauthorizedOwner" - }, - { - "index": 14, - "name": "UnauthorizedClusterManager" - }, - { - "index": 15, - "name": "ClusterManagerIsNotTrusted" - }, - { - "index": 16, - "name": "TransferFailed" - }, - { - "index": 17, - "name": "InsufficientBalance" - }, - { - "index": 18, - "name": "InsufficientResources" - }, - { - "index": 19, - "name": "Unauthorized" - }, - { - "index": 20, - "name": "UnknownNode" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "Error" - ] - } - }, - { - "id": 49, - "type": { - "def": { - "tuple": [ - 50, - 9 - ] - } - } - }, - { - "id": 50, - "type": { - "def": { - "sequence": { - "type": 46 - } - } - } - }, - { - "id": 51, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 52 - } - ], - "index": 0, - "name": "Ok" - }, - { - "fields": [ - { - "type": 48 - } - ], - "index": 1, - "name": "Err" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 52 - }, - { - "name": "E", - "type": 48 - } - ], - "path": [ - "Result" - ] - } - }, - { - "id": 52, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "cluster_id", - "type": 9, - "typeName": "ClusterId" - }, - { - "name": "cluster", - "type": 18, - "typeName": "Cluster" - }, - { - "name": "params", - "type": 16, - "typeName": "Params" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cluster", - "entity", - "ClusterStatus" - ] - } - }, - { - "id": 53, - "type": { - "def": { - "tuple": [ - 54, - 9 - ] - } - } - }, - { - "id": 54, - "type": { - "def": { - "sequence": { - "type": 52 - } - } - } - }, - { - "id": 55, - "type": { - "def": { - "sequence": { - "type": 56 - } - } - } - }, - { - "id": 56, - "type": { - "def": { - "tuple": [ - 8, - 12 - ] - } - } - }, - { - "id": 57, - "type": { - "def": { - "sequence": { - "type": 58 - } - } - } - }, - { - "id": 58, - "type": { - "def": { - "tuple": [ - 9, - 12 - ] - } - } - }, - { - "id": 59, - "type": { - "def": { - "sequence": { - "type": 60 - } - } - } - }, - { - "id": 60, - "type": { - "def": { - "tuple": [ - 9, - 9 - ] - } - } - }, - { - "id": 61, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 62 - } - ], - "index": 0, - "name": "Ok" - }, - { - "fields": [ - { - "type": 48 - } - ], - "index": 1, - "name": "Err" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 62 - }, - { - "name": "E", - "type": 48 - } - ], - "path": [ - "Result" - ] - } - }, - { - "id": 62, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "cluster_id", - "type": 9, - "typeName": "ClusterId" - }, - { - "name": "cluster", - "type": 25, - "typeName": "CdnCluster" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cdn_cluster", - "entity", - "CdnClusterStatus" - ] - } - }, - { - "id": 63, - "type": { - "def": { - "tuple": [ - 64, - 9 - ] - } - } - }, - { - "id": 64, - "type": { - "def": { - "sequence": { - "type": 62 - } - } - } - }, - { - "id": 65, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "start", - "type": 23, - "typeName": "u64" - }, - { - "name": "interval", - "type": 23, - "typeName": "u64" - }, - { - "name": "commit_duration", - "type": 23, - "typeName": "u64" - }, - { - "name": "validation_duration", - "type": 23, - "typeName": "u64" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "committer", - "store", - "EraConfig" - ] - } - }, - { - "id": 66, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "current_era", - "type": 23, - "typeName": "u64" - }, - { - "name": "current_phase", - "type": 67, - "typeName": "Phase" - }, - { - "name": "previous_era", - "type": 23, - "typeName": "u64" - }, - { - "name": "prev_era_from_timestamp", - "type": 23, - "typeName": "u64" - }, - { - "name": "prev_era_to_timestamp", - "type": 23, - "typeName": "u64" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "committer", - "store", - "EraStatus" - ] - } - }, - { - "id": 67, - "type": { - "def": { - "variant": { - "variants": [ - { - "index": 0, - "name": "Commit" - }, - { - "index": 1, - "name": "Valiadation" - }, - { - "index": 2, - "name": "Payout" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "committer", - "store", - "Phase" - ] - } - }, - { - "id": 68, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 69 - } - ], - "index": 0, - "name": "Ok" - }, - { - "fields": [ - { - "type": 48 - } - ], - "index": 1, - "name": "Err" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 69 - }, - { - "name": "E", - "type": 48 - } - ], - "path": [ - "Result" - ] - } - }, - { - "id": 69, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "node_id", - "type": 9, - "typeName": "NodeId" - }, - { - "name": "node", - "type": 27, - "typeName": "CdnNode" - }, - { - "name": "params", - "type": 16, - "typeName": "Params" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "cdn_node", - "entity", - "CdnNodeStatus" - ] - } - }, - { - "id": 70, - "type": { - "def": { - "tuple": [ - 71, - 9 - ] - } - } - }, - { - "id": 71, - "type": { - "def": { - "sequence": { - "type": 69 - } - } - } - }, - { - "id": 72, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 73 - } - ], - "index": 0, - "name": "Ok" - }, - { - "fields": [ - { - "type": 48 - } - ], - "index": 1, - "name": "Err" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 73 - }, - { - "name": "E", - "type": 48 - } - ], - "path": [ - "Result" - ] - } - }, - { - "id": 73, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "node_id", - "type": 9, - "typeName": "NodeId" - }, - { - "name": "node", - "type": 30, - "typeName": "Node" - }, - { - "name": "params", - "type": 16, - "typeName": "Params" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "node", - "entity", - "NodeStatus" - ] - } - }, - { - "id": 74, - "type": { - "def": { - "tuple": [ - 75, - 9 - ] - } - } - }, - { - "id": 75, - "type": { - "def": { - "sequence": { - "type": 73 - } - } - } - }, - { - "id": 76, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 33 - } - ], - "index": 0, - "name": "Ok" - }, - { - "fields": [ - { - "type": 48 - } - ], - "index": 1, - "name": "Err" - } - ] - } - }, - "params": [ - { - "name": "T", - "type": 33 - }, - { - "name": "E", - "type": 48 - } - ], - "path": [ - "Result" - ] - } - }, - { - "id": 77, - "type": { - "def": { - "variant": { - "variants": [ - { - "fields": [ - { - "type": 8, - "typeName": "AccountId" - } - ], - "index": 0, - "name": "ManagerTrustedBy" - }, - { - "index": 1, - "name": "SetExchangeRate" - }, - { - "index": 2, - "name": "SuperAdmin" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "perm", - "entity", - "Permission" - ] - } - }, - { - "id": 78, - "type": { - "def": { - "composite": { - "fields": [ - { - "name": "network_fee_bp", - "type": 12, - "typeName": "BasisPoints" - }, - { - "name": "network_fee_destination", - "type": 8, - "typeName": "AccountId" - }, - { - "name": "cluster_management_fee_bp", - "type": 12, - "typeName": "BasisPoints" - } - ] - } - }, - "path": [ - "ddc_bucket", - "ddc_bucket", - "network_fee", - "FeeConfig" - ] - } - } - ] - } -} \ No newline at end of file diff --git a/bucket/scripts/package-lock.json b/bucket/scripts/package-lock.json deleted file mode 100644 index 0411d6de..00000000 --- a/bucket/scripts/package-lock.json +++ /dev/null @@ -1,789 +0,0 @@ -{ - "name": "scripts", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "dependencies": { - "@polkadot/api": "^10.9.1", - "@polkadot/api-contract": "^10.9.1", - "@polkadot/util-crypto": "^12.3.2" - } - }, - "node_modules/@noble/curves": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", - "dependencies": { - "@noble/hashes": "1.3.1" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@polkadot/api": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-10.9.1.tgz", - "integrity": "sha512-ND/2UqZBWvtt4PfV03OStTKg0mxmPk4UpMAgJKutdgsz/wP9CYJ1KbjwFgPNekL9JnzbKQsWyQNPVrcw7kQk8A==", - "dependencies": { - "@polkadot/api-augment": "10.9.1", - "@polkadot/api-base": "10.9.1", - "@polkadot/api-derive": "10.9.1", - "@polkadot/keyring": "^12.3.1", - "@polkadot/rpc-augment": "10.9.1", - "@polkadot/rpc-core": "10.9.1", - "@polkadot/rpc-provider": "10.9.1", - "@polkadot/types": "10.9.1", - "@polkadot/types-augment": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/types-create": "10.9.1", - "@polkadot/types-known": "10.9.1", - "@polkadot/util": "^12.3.1", - "@polkadot/util-crypto": "^12.3.1", - "eventemitter3": "^5.0.1", - "rxjs": "^7.8.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/api-augment": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-10.9.1.tgz", - "integrity": "sha512-kRZZvCFVcN4hAH4dJ+Qzfdy27/4EEq3oLDf3ihj0LTVrAezSWcKPGE3EVFy+Mn6Lo4SUc7RVyoKvIUhSk2l4Dg==", - "dependencies": { - "@polkadot/api-base": "10.9.1", - "@polkadot/rpc-augment": "10.9.1", - "@polkadot/types": "10.9.1", - "@polkadot/types-augment": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/util": "^12.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/api-base": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-10.9.1.tgz", - "integrity": "sha512-Q3m2KzlceMK2kX8bhnUZWk3RT6emmijeeFZZQgCePpEcrSeNjnqG4qjuTPgkveaOkUT8MAoDc5Avuzcc2jlW9g==", - "dependencies": { - "@polkadot/rpc-core": "10.9.1", - "@polkadot/types": "10.9.1", - "@polkadot/util": "^12.3.1", - "rxjs": "^7.8.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/api-contract": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-contract/-/api-contract-10.9.1.tgz", - "integrity": "sha512-BJjFYSFtsUlClC3mgvPNQ5h/7LZd5gVfexwl+mDgLd/6SN4dUBQjIXhlIL5a1cGYjq3EROuu7t0agG2DIaiZMQ==", - "dependencies": { - "@polkadot/api": "10.9.1", - "@polkadot/api-augment": "10.9.1", - "@polkadot/types": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/types-create": "10.9.1", - "@polkadot/util": "^12.3.1", - "@polkadot/util-crypto": "^12.3.1", - "rxjs": "^7.8.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/api-derive": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-10.9.1.tgz", - "integrity": "sha512-mRud1UZCFIc4Z63qAoGSIHh/foyUYADfy1RQYCmPpeFKfIdCIrHpd7xFdJXTOMYOS0BwlM6u4qli/ZT4XigezQ==", - "dependencies": { - "@polkadot/api": "10.9.1", - "@polkadot/api-augment": "10.9.1", - "@polkadot/api-base": "10.9.1", - "@polkadot/rpc-core": "10.9.1", - "@polkadot/types": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/util": "^12.3.1", - "@polkadot/util-crypto": "^12.3.1", - "rxjs": "^7.8.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/keyring": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-12.3.2.tgz", - "integrity": "sha512-NTdtDeI0DP9l/45hXynNABeP5VB8piw5YR+CbUxK2e36xpJWVXwbcOepzslg5ghE9rs8UKJb30Z/HqTU4sBY0Q==", - "dependencies": { - "@polkadot/util": "12.3.2", - "@polkadot/util-crypto": "12.3.2", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "12.3.2", - "@polkadot/util-crypto": "12.3.2" - } - }, - "node_modules/@polkadot/networks": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-12.3.2.tgz", - "integrity": "sha512-uCkyybKoeEm1daKr0uT/9oNDHDDzCy2/ZdVl346hQqfdR1Ct3BaxMjxqvdmb5N8aCw0cBWSfgsxAYtw8ESmllQ==", - "dependencies": { - "@polkadot/util": "12.3.2", - "@substrate/ss58-registry": "^1.40.0", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/rpc-augment": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-10.9.1.tgz", - "integrity": "sha512-MaLHkNlyqN20ZRYr6uNd1BZr1OsrnX9qLAmsl0mcrri1vPGRH6VHjfFH1RBLkikpWD82v17g0l2hLwdV1ZHMcw==", - "dependencies": { - "@polkadot/rpc-core": "10.9.1", - "@polkadot/types": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/util": "^12.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/rpc-core": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-10.9.1.tgz", - "integrity": "sha512-ZtA8B8SfXSAwVkBlCcKRHw0eSM7ec/sbiNOM5GasXPeRujUgT7lOwSH2GbUZSqe9RfRDMp6DvO9c2JoGc3LLWw==", - "dependencies": { - "@polkadot/rpc-augment": "10.9.1", - "@polkadot/rpc-provider": "10.9.1", - "@polkadot/types": "10.9.1", - "@polkadot/util": "^12.3.1", - "rxjs": "^7.8.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/rpc-provider": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-10.9.1.tgz", - "integrity": "sha512-4QzT2QzD+320+eT6b79sGAA85Tt3Bb8fQvse4r5Mom2iiBd2SO81vOhxSAOaIe4GUsw25VzFJmsbe7+OObItdg==", - "dependencies": { - "@polkadot/keyring": "^12.3.1", - "@polkadot/types": "10.9.1", - "@polkadot/types-support": "10.9.1", - "@polkadot/util": "^12.3.1", - "@polkadot/util-crypto": "^12.3.1", - "@polkadot/x-fetch": "^12.3.1", - "@polkadot/x-global": "^12.3.1", - "@polkadot/x-ws": "^12.3.1", - "eventemitter3": "^5.0.1", - "mock-socket": "^9.2.1", - "nock": "^13.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - }, - "optionalDependencies": { - "@substrate/connect": "0.7.26" - } - }, - "node_modules/@polkadot/types": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-10.9.1.tgz", - "integrity": "sha512-AG33i2ZGGfq7u+5rkAdGrXAQHHl844/Yv+junH5ZzX69xiCoWO1bH/yzDUNBdpki2GlACWvF9nLYh3F2tVF93w==", - "dependencies": { - "@polkadot/keyring": "^12.3.1", - "@polkadot/types-augment": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/types-create": "10.9.1", - "@polkadot/util": "^12.3.1", - "@polkadot/util-crypto": "^12.3.1", - "rxjs": "^7.8.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/types-augment": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-10.9.1.tgz", - "integrity": "sha512-OY9/jTMFRFqYdkUnfcGwqMLC64A0Q25bjvCuVQCVjsPFKE3wl0Kt5rNT01eV2UmLXrR6fY0xWbR2w80bLA7CIQ==", - "dependencies": { - "@polkadot/types": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/util": "^12.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/types-codec": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-10.9.1.tgz", - "integrity": "sha512-mJ5OegKGraY1FLvEa8FopRCr3pQrhDkcn5RNOjmgJQozENVeRaxhk0NwxYz7IojFvSDnKnc6lNQfKaaSe5pLHg==", - "dependencies": { - "@polkadot/util": "^12.3.1", - "@polkadot/x-bigint": "^12.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/types-create": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-10.9.1.tgz", - "integrity": "sha512-OVz50MGTTuiuVnRP/zAx4CTuLioc0hsiwNwqN2lNhmIJGtnQ4Vy/7mQRsIWehiYz6g0Vzzm5B3qWkTXO1NSN5w==", - "dependencies": { - "@polkadot/types-codec": "10.9.1", - "@polkadot/util": "^12.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/types-known": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-10.9.1.tgz", - "integrity": "sha512-zCMVWc4pJtkbMFPu72bD4IhvV/gkHXPX3C5uu92WdmCfnn0vEIEsMKWlVXVVvQQZKAqvs/awpqIfrUtEViOGEA==", - "dependencies": { - "@polkadot/networks": "^12.3.1", - "@polkadot/types": "10.9.1", - "@polkadot/types-codec": "10.9.1", - "@polkadot/types-create": "10.9.1", - "@polkadot/util": "^12.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/types-support": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-10.9.1.tgz", - "integrity": "sha512-XsieuLDsszvMZQlleacQBfx07i/JkwQV/UxH9q8Hz7Okmaz9pEVEW1h3ka2/cPuC7a4l32JhaORBUYshBZNdJg==", - "dependencies": { - "@polkadot/util": "^12.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/util": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-12.3.2.tgz", - "integrity": "sha512-y/JShcGyOamCUiSIg++XZuLHt1ktSKBaSH2K5Nw5NXlgP0+7am+GZzqPB8fQ4qhYLruEOv+YRiz0GC1Zr9S+wg==", - "dependencies": { - "@polkadot/x-bigint": "12.3.2", - "@polkadot/x-global": "12.3.2", - "@polkadot/x-textdecoder": "12.3.2", - "@polkadot/x-textencoder": "12.3.2", - "@types/bn.js": "^5.1.1", - "bn.js": "^5.2.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/util-crypto": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-12.3.2.tgz", - "integrity": "sha512-pTpx+YxolY0BDT4RcGmgeKbHHD/dI6Ll9xRsqmVdIjpcVVY20uDNTyXs81ZNtfKgyod1y9JQkfNv2Dz9iEpTkQ==", - "dependencies": { - "@noble/curves": "1.1.0", - "@noble/hashes": "1.3.1", - "@polkadot/networks": "12.3.2", - "@polkadot/util": "12.3.2", - "@polkadot/wasm-crypto": "^7.2.1", - "@polkadot/wasm-util": "^7.2.1", - "@polkadot/x-bigint": "12.3.2", - "@polkadot/x-randomvalues": "12.3.2", - "@scure/base": "1.1.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "12.3.2" - } - }, - "node_modules/@polkadot/wasm-bridge": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.2.1.tgz", - "integrity": "sha512-uV/LHREDBGBbHrrv7HTki+Klw0PYZzFomagFWII4lp6Toj/VCvRh5WMzooVC+g/XsBGosAwrvBhoModabyHx+A==", - "dependencies": { - "@polkadot/wasm-util": "7.2.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "*", - "@polkadot/x-randomvalues": "*" - } - }, - "node_modules/@polkadot/wasm-crypto": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-7.2.1.tgz", - "integrity": "sha512-SA2+33S9TAwGhniKgztVN6pxUKpGfN4Tre/eUZGUfpgRkT92wIUT2GpGWQE+fCCqGQgADrNiBcwt6XwdPqMQ4Q==", - "dependencies": { - "@polkadot/wasm-bridge": "7.2.1", - "@polkadot/wasm-crypto-asmjs": "7.2.1", - "@polkadot/wasm-crypto-init": "7.2.1", - "@polkadot/wasm-crypto-wasm": "7.2.1", - "@polkadot/wasm-util": "7.2.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "*", - "@polkadot/x-randomvalues": "*" - } - }, - "node_modules/@polkadot/wasm-crypto-asmjs": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.2.1.tgz", - "integrity": "sha512-z/d21bmxyVfkzGsKef/FWswKX02x5lK97f4NPBZ9XBeiFkmzlXhdSnu58/+b1sKsRAGdW/Rn/rTNRDhW0GqCAg==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "*" - } - }, - "node_modules/@polkadot/wasm-crypto-init": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.2.1.tgz", - "integrity": "sha512-GcEXtwN9LcSf32V9zSaYjHImFw16hCyo2Xzg4GLLDPPeaAAfbFr2oQMgwyDbvBrBjLKHVHjsPZyGhXae831amw==", - "dependencies": { - "@polkadot/wasm-bridge": "7.2.1", - "@polkadot/wasm-crypto-asmjs": "7.2.1", - "@polkadot/wasm-crypto-wasm": "7.2.1", - "@polkadot/wasm-util": "7.2.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "*", - "@polkadot/x-randomvalues": "*" - } - }, - "node_modules/@polkadot/wasm-crypto-wasm": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.2.1.tgz", - "integrity": "sha512-DqyXE4rSD0CVlLIw88B58+HHNyrvm+JAnYyuEDYZwCvzUWOCNos/DDg9wi/K39VAIsCCKDmwKqkkfIofuOj/lA==", - "dependencies": { - "@polkadot/wasm-util": "7.2.1", - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "*" - } - }, - "node_modules/@polkadot/wasm-util": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.2.1.tgz", - "integrity": "sha512-FBSn/3aYJzhN0sYAYhHB8y9JL8mVgxLy4M1kUXYbyo+8GLRQEN5rns8Vcb8TAlIzBWgVTOOptYBvxo0oj0h7Og==", - "dependencies": { - "tslib": "^2.5.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "*" - } - }, - "node_modules/@polkadot/x-bigint": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-12.3.2.tgz", - "integrity": "sha512-JLqLgfGXe/x+hZJETd5ZqfpVsbwyMsH5Nn1Q20ineMMjXN/ig+kVR8Mc15LXBMuw4g7LldFW6UUrotWnuMI8Yw==", - "dependencies": { - "@polkadot/x-global": "12.3.2", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/x-fetch": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-12.3.2.tgz", - "integrity": "sha512-3IEuZ5S+RI/t33NsdPLIIa5COfDCfpUW2sbaByEczn75aD1jLqJZSEDwiBniJ2osyNd4uUxBf6e5jw7LAZeZJg==", - "dependencies": { - "@polkadot/x-global": "12.3.2", - "node-fetch": "^3.3.1", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/x-global": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-12.3.2.tgz", - "integrity": "sha512-yVZq6oIegjlyh5rUZiTklgu+fL+W/DG1ypEa02683tUCB3avV5cA3PAHKptMSlb6FpweHu37lKKrqfAWrraDxg==", - "dependencies": { - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/x-randomvalues": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-12.3.2.tgz", - "integrity": "sha512-ywjIs8CWpvOGmq+3cGCNPOHxAjPHdBUiXyDccftx5BRVdmtbt36gK/V84bKr6Xs73FGu0jprUAOSRRsLZX/3dg==", - "dependencies": { - "@polkadot/x-global": "12.3.2", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "@polkadot/util": "12.3.2", - "@polkadot/wasm-util": "*" - } - }, - "node_modules/@polkadot/x-textdecoder": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-12.3.2.tgz", - "integrity": "sha512-lY5bfA5xArJRWEJlYOlQQMJeTjWD8s0yMhchirVgf5xj8Id9vPGeUoneH+VFDEwgXxrqBvDFJ4smN4T/r6a/fg==", - "dependencies": { - "@polkadot/x-global": "12.3.2", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/x-textencoder": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-12.3.2.tgz", - "integrity": "sha512-iP3qEBiHzBckQ9zeY7ZHRWuu7mCEg5SMpOugs6UODRk8sx6KHzGQYlghBbWLit0uppPDVE0ifEwZ2n73djJHWQ==", - "dependencies": { - "@polkadot/x-global": "12.3.2", - "tslib": "^2.5.3" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@polkadot/x-ws": { - "version": "12.3.2", - "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-12.3.2.tgz", - "integrity": "sha512-yM9Z64pLNlHpJE43+Xtr+iUXmYpFFY5u5hrke2PJt13O48H8f9Vb9cRaIh94appLyICoS0aekGhDkGH+MCspBA==", - "dependencies": { - "@polkadot/x-global": "12.3.2", - "tslib": "^2.5.3", - "ws": "^8.13.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/@scure/base": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", - "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@substrate/connect": { - "version": "0.7.26", - "resolved": "https://registry.npmjs.org/@substrate/connect/-/connect-0.7.26.tgz", - "integrity": "sha512-uuGSiroGuKWj1+38n1kY5HReer5iL9bRwPCzuoLtqAOmI1fGI0hsSI2LlNQMAbfRgr7VRHXOk5MTuQf5ulsFRw==", - "optional": true, - "dependencies": { - "@substrate/connect-extension-protocol": "^1.0.1", - "eventemitter3": "^4.0.7", - "smoldot": "1.0.4" - } - }, - "node_modules/@substrate/connect-extension-protocol": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-1.0.1.tgz", - "integrity": "sha512-161JhCC1csjH3GE5mPLEd7HbWtwNSPJBg3p1Ksz9SFlTzj/bgEwudiRN2y5i0MoLGCIJRYKyKGMxVnd29PzNjg==", - "optional": true - }, - "node_modules/@substrate/connect/node_modules/eventemitter3": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", - "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", - "optional": true - }, - "node_modules/@substrate/ss58-registry": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.40.0.tgz", - "integrity": "sha512-QuU2nBql3J4KCnOWtWDw4n1K4JU0T79j54ZZvm/9nhsX6AIar13FyhsaBfs6QkJ2ixTQAnd7TocJIoJRWbqMZA==" - }, - "node_modules/@types/bn.js": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz", - "integrity": "sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "20.3.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz", - "integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==" - }, - "node_modules/bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/mock-socket": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.2.1.tgz", - "integrity": "sha512-aw9F9T9G2zpGipLLhSNh6ZpgUyUl4frcVmRN08uE1NWPWg43Wx6+sGPDbQ7E5iFZZDJW5b5bypMeAEHqTbIFag==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/nock": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.3.1.tgz", - "integrity": "sha512-vHnopocZuI93p2ccivFyGuUfzjq2fxNyNurp7816mlT5V5HF4SzXu8lvLrVzBbNqzs+ODooZ6OksuSUNM7Njkw==", - "dependencies": { - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "lodash": "^4.17.21", - "propagate": "^2.0.0" - }, - "engines": { - "node": ">= 10.13" - } - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.1.tgz", - "integrity": "sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==", - "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" - } - }, - "node_modules/pako": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", - "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", - "optional": true - }, - "node_modules/propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/smoldot": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-1.0.4.tgz", - "integrity": "sha512-N3TazI1C4GGrseFH/piWyZCCCRJTRx2QhDfrUKRT4SzILlW5m8ayZ3QTKICcz1C/536T9cbHHJyP7afxI6Mi1A==", - "optional": true, - "dependencies": { - "pako": "^2.0.4", - "ws": "^8.8.1" - } - }, - "node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==" - }, - "node_modules/web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", - "engines": { - "node": ">= 8" - } - }, - "node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - } - } -} diff --git a/bucket/scripts/package.json b/bucket/scripts/package.json deleted file mode 100644 index bc305466..00000000 --- a/bucket/scripts/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "module", - "dependencies": { - "@polkadot/api": "^10.9.1", - "@polkadot/api-contract": "^10.9.1", - "@polkadot/util-crypto": "^12.3.2" - } -} From 7e1f9dd711f4f50b6e743011230188f69d55f8f3 Mon Sep 17 00:00:00 2001 From: yahortsaryk Date: Tue, 4 Jul 2023 01:18:40 +0200 Subject: [PATCH 89/89] chore(lib): version 1.0.0 --- Cargo.lock | 2 +- bucket/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1da8286f..9224d38f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,7 +95,7 @@ dependencies = [ [[package]] name = "ddc_bucket" -version = "0.5.2" +version = "1.0.0" dependencies = [ "ink_allocator", "ink_env", diff --git a/bucket/Cargo.toml b/bucket/Cargo.toml index 8fc4ab87..ea5a2b9a 100755 --- a/bucket/Cargo.toml +++ b/bucket/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ddc_bucket" -version = "0.5.2" +version = "1.0.0" authors = ["Aurélien Nicolas "] edition = "2021" description = "DDC v2 Smart Contracts -- Orchestrate the network around clusters and buckets"