Skip to content
This repository has been archived by the owner on May 16, 2024. It is now read-only.

Commit

Permalink
fix(lib): guards for packed layouts (vectors) are added
Browse files Browse the repository at this point in the history
  • Loading branch information
yahortsaryk committed Jun 30, 2023
1 parent acc9e77 commit 860fac7
Show file tree
Hide file tree
Showing 9 changed files with 81 additions and 42 deletions.
4 changes: 2 additions & 2 deletions bucket/ddc_bucket/account/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() });

Expand Down Expand Up @@ -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);
Expand Down
12 changes: 11 additions & 1 deletion bucket/ddc_bucket/account/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion bucket/ddc_bucket/bucket/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<AccountId>) -> Result<BucketId> {
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)
Expand Down
33 changes: 20 additions & 13 deletions bucket/ddc_bucket/cdn_node/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<CdnNodeKey, CdnNode>,
// 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<CdnNodeKey>
}

Expand All @@ -26,18 +29,22 @@ impl CdnNodeStore {
) -> Result<CdnNodeKey> {

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<CdnNode> {
Expand Down
18 changes: 16 additions & 2 deletions bucket/ddc_bucket/cluster/entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions bucket/ddc_bucket/cluster/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 {
Expand Down
37 changes: 21 additions & 16 deletions bucket/ddc_bucket/node/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<NodeKey, Node>,
// 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<NodeKey>
}

Expand All @@ -28,19 +29,23 @@ impl NodeStore {
) -> Result<NodeKey> {

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<Node> {
Expand Down
10 changes: 5 additions & 5 deletions bucket/ddc_bucket/topology/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))]
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down
3 changes: 3 additions & 0 deletions bucket/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1686,7 +1686,10 @@ pub mod ddc_bucket {
ClusterIsNotEmpty,
TopologyIsNotCreated(ClusterId),
TopologyAlreadyExists,
NodesSizeExceedsLimit,
CdnNodesSizeExceedsLimit,
VNodesSizeExceedsLimit,
AccountsSizeExceedsLimit,
NodeIsNotAddedToCluster(ClusterId),
NodeIsAddedToCluster(ClusterId),
CdnNodeIsNotAddedToCluster(ClusterId),
Expand Down

0 comments on commit 860fac7

Please sign in to comment.