Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[Market+MPoW] Add passive check from storage order #131

Merged
merged 2 commits into from
May 19, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 64 additions & 24 deletions cstrml/tee/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,15 +262,37 @@ impl<T: Trait> Module<T> {
return;
}

// 2. Update id's work rzeport, get id's workload and total workload
// 2. Update id's work report, get id's workload and total workload
let mut total_used = 0;
let mut total_reserved = 0;

// TODO: avoid iterate all identities
let workload_map: Vec<(T::AccountId, u128)> = <TeeIdentities<T>>::iter().map(|(controller, _)| {
let (reserved, used) = Self::update_and_get_workload(&controller, current_rs);
// a. calculate this controller's order file map
let mut order_files: Vec<(MerkleRoot, Hash)> = vec![];
if let Some(provision) = T::MarketInterface::providers(&controller) {
order_files = provision.file_map.values()
.filter_map(|order_id| {
// Get order status(should exist) and (maybe) change the status
let sorder =
T::MarketInterface::maybe_get_sorder(order_id).unwrap_or_default();
if sorder.order_status == OrderStatus::Success {
Some((sorder.file_identifier, order_id.clone()))
} else {
None
}
})
.collect();
}

// b. calculate controller's own reserved and used space
let (reserved, used) = Self::update_and_get_workload(&controller, &order_files, current_rs);

// c. add to total
total_used += used;
total_reserved += reserved;

// d. return my own to construct workload map
(controller.clone(), used + reserved)
}).collect();

Expand All @@ -283,7 +305,6 @@ impl<T: Trait> Module<T> {

// 4. Update stake limit
for (controller, own_workload) in workload_map {
// TODO: passive market order test in here, check and (maybe) update the order's status(success -> failed)
T::Works::report_works(&controller, own_workload, total_workload);
}
}
Expand Down Expand Up @@ -314,25 +335,26 @@ impl<T: Trait> Module<T> {
let file_map = T::MarketInterface::providers(who).unwrap_or_default().file_map;
updated_wr.used = wr.files.iter().fold(0, |used, (f_id, f_size)| {
if let Some(order_id) = file_map.get(f_id) {
// Get order status and (maybe) change the status
if let Some(mut sorder) = T::MarketInterface::maybe_get_sorder(order_id) {
// TODO: we should specially handle `Failed` status
if sorder.order_status != OrderStatus::Success {
// 1. Change order status to `Success`
sorder.order_status = OrderStatus::Success;

// 2. Reset `expired_on` for new order
if sorder.order_status == OrderStatus::Pending {
let current_block_numeric = Self::get_current_block_number();
// go panic if `current_block_numeric` > `created_on`
sorder.expired_on += current_block_numeric - sorder.created_on;
}

// 3. (Maybe) set sorder
T::MarketInterface::maybe_set_sorder(order_id, &sorder);
// Get order status(should exist) and (maybe) change the status
let mut sorder =
T::MarketInterface::maybe_get_sorder(order_id).unwrap_or_default();

// TODO: we should specially handle `Failed` status
if sorder.order_status != OrderStatus::Success {
// 1. Change order status to `Success`
sorder.order_status = OrderStatus::Success;

// 2. Reset `expired_on` for new order
if sorder.order_status == OrderStatus::Pending {
let current_block_numeric = Self::get_current_block_number();
// go panic if `current_block_numeric` > `created_on`
sorder.expired_on += current_block_numeric - sorder.created_on;
}
return used + *f_size

// 3. (Maybe) set sorder
T::MarketInterface::maybe_set_sorder(order_id, &sorder);
}
return used + *f_size
}
used
});
Expand Down Expand Up @@ -361,12 +383,30 @@ impl<T: Trait> Module<T> {

/// Get updated workload by controller account,
/// this function should only be called in the new era
/// otherwise, it will be an void in this recursive loop,
/// return the (reserved, used) storage of this controller
fn update_and_get_workload(controller: &T::AccountId, current_rs: u64) -> (u128, u128) {
// 1. Judge if this controller reported works in this current era
/// otherwise, it will be an void in this recursive loop, it mainly includes:
/// 1. passive check according to market order, it (maybe) update `used` and `order_status`;
/// 2. (maybe) remove outdated work report
/// 3. return the (reserved, used) storage of this controller account
fn update_and_get_workload(controller: &T::AccountId, order_map: &Vec<(MerkleRoot, Hash)>, current_rs: u64) -> (u128, u128) {
// Judge if this controller reported works in this current era
if let Some(wr) = Self::work_reports(controller) {
if Self::reported_in_slot(controller, current_rs) {
// 1. Get all work report files
let wr_files: Vec<MerkleRoot> = wr.files.iter().map(|(f_id, _)| f_id.clone()).collect();

// 2. Check every order files are stored by controller
for (f_id, order_id) in order_map {
if !wr_files.contains(f_id) {
// 3. Set status to failed
let mut sorder =
T::MarketInterface::maybe_get_sorder(order_id).unwrap_or_default();
sorder.order_status = OrderStatus::Failed;
T::MarketInterface::maybe_set_sorder(order_id, &sorder);
// TODO: add market slashing here
}
}

// 3. Return reserved and used
(wr.reserved as u128, wr.used as u128)
} else {
// Remove work report when it is outdated
Expand Down
4 changes: 2 additions & 2 deletions cstrml/tee/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ pub fn run_to_block(n: u64) {
}
}

pub fn upsert_sorder_to_provider(who: &AccountId, f_id: &MerkleRoot, rd: u8) {
pub fn upsert_sorder_to_provider(who: &AccountId, f_id: &MerkleRoot, rd: u8, os: OrderStatus) {
let mut file_map = Market::providers(who).unwrap_or_default().file_map;
let sorder_id: Hash = Hash::repeat_byte(rd);
let sorder = StorageOrder {
Expand All @@ -145,7 +145,7 @@ pub fn upsert_sorder_to_provider(who: &AccountId, f_id: &MerkleRoot, rd: u8) {
expired_on: 0,
provider: who.clone(),
client: who.clone(),
order_status: Default::default()
order_status: os
};
file_map.insert(f_id.clone(), sorder_id.clone());
let provision = Provision {
Expand Down
41 changes: 37 additions & 4 deletions cstrml/tee/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,27 @@ fn get_valid_work_report() -> WorkReport {
}
}

fn add_valid_sorder() {
fn add_pending_sorder() {
let account: AccountId = Sr25519Keyring::Bob.to_account_id();
let files: Vec<Vec<u8>> = [
hex::decode("5bb706320afc633bfb843108e492192b17d2b6b9d9ee0b795ee95417fe08b660").unwrap(),
hex::decode("88cdb315c8c37e2dc00fa2a8c7fe51b8149b363d29f404441982f96d2bbae65f").unwrap()
].to_vec();

for (idx, file) in files.iter().enumerate() {
upsert_sorder_to_provider(&account, file, idx as u8);
upsert_sorder_to_provider(&account, file, idx as u8, OrderStatus::Pending);
}
}

fn add_success_sorder() {
let account: AccountId = Sr25519Keyring::Bob.to_account_id();
let file: MerkleRoot =
hex::decode("5bb706320afc633bfb843108e492192b17d2b6b9d9ee0b795ee95417fe08b661").unwrap();

upsert_sorder_to_provider(&account, &file, 99, OrderStatus::Success);

}

#[test]
fn test_for_register_identity_success() {
new_test_ext().execute_with(|| {
Expand Down Expand Up @@ -198,7 +207,7 @@ fn test_for_report_works_success() {
// generate 303 blocks first
run_to_block(303);
// prepare sorder
add_valid_sorder();
add_pending_sorder();

let account: AccountId = Sr25519Keyring::Bob.to_account_id();

Expand All @@ -213,7 +222,8 @@ fn test_for_report_works_success() {
// Check workloads after work report
assert_eq!(Tee::reserved(), 4294967296);
assert_eq!(Tee::used(), 402868224);
assert_eq!(Market::storage_orders(Hash::repeat_byte(1)).unwrap_or_default().order_status, OrderStatus::Success);
assert_eq!(Market::storage_orders(Hash::repeat_byte(1)).unwrap_or_default().order_status,
OrderStatus::Success);
});
}

Expand Down Expand Up @@ -345,6 +355,29 @@ fn test_for_work_report_sig_check_failed() {
});
}

#[test]
fn test_for_wr_check_failed_order() {
new_test_ext().execute_with(|| {
let account: AccountId = Sr25519Keyring::Bob.to_account_id();
add_success_sorder();
// generate 303 blocks first
run_to_block(303);

// report works should ok
assert_ok!(Tee::report_works(
Origin::signed(account.clone()),
get_valid_work_report()
));

// check work report and workload, current_report_slot updating should work
Tee::update_identities();
// Check this 99 order should be failed
assert_eq!(Market::storage_orders(Hash::repeat_byte(99)).unwrap_or_default().order_status,
OrderStatus::Failed);

});
}

#[test]
fn test_for_outdated_work_reports() {
new_test_ext().execute_with(|| {
Expand Down