Skip to content

Commit 4d4501b

Browse files
committed
Implement in-order requirement between input and output for multi input txns
Implemented below : 1. Removed the out-of-order b/w input & output for Implemented the in-order for below : 1. ListKittyForSale 2. DelistKittyForSale 3. UpdateName 4.UpdatePrice For Breed operation, only 1 tradable kitty can be traded at the same time in the same txn.
1 parent 1f5855b commit 4d4501b

File tree

4 files changed

+389
-144
lines changed

4 files changed

+389
-144
lines changed

wardrobe/kitties/src/lib.rs

+52-28
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,26 @@
66
//! - **Create:** Generate a new kitty.
77
//! To submit a valid transaction for creating a kitty, adhere to the following structure:
88
//! 1. Input must be empty.
9-
//! 2. Output must contain only the newly created kitty as a child.
10-
9+
//! 2. Output must contain only the newly created kittities as a child.
10+
//!
11+
//! **Note 1:** Multiple kitties can be created at the same time in the same txn..
12+
//!
1113
//! - **Update Name:** Modify the name of a kitty.
1214
//! To submit a valid transaction for updating a kitty's name, adhere to the following structure:
1315
//! 1. Input must be the kitty to be updated.
1416
//! 2. Output must contain the kitty with the updated name.
1517
//!
16-
//! **Note:** All other properties such as DNA, parents, free breedings, etc., must remain unaltered in the output.
18+
//! **Note 1:** All other properties such as DNA, parents, free breedings, etc., must remain unaltered in the output.
19+
//! **Note 2:** The input and output kitties must follow same order.
1720
//!
1821
//! - **Breed:** Breeds a new kitty using mom and dad based on below factors
19-
//! 1.) Mom and Tired have to be in a state where they are ready to breed
22+
//! 1.) Mom and Dad have to be in a state where they are ready to breed
2023
//! 2.) Each Mom and Dad have some DNA and the child will have unique DNA combined from the both of them
2124
//! Linkable back to the Mom and Dad
2225
//! 3.) The game also allows Kitties to have a cooling off period inbetween breeding before they can be bred again.
2326
//! 4.) A rest operation allows for a Mom Kitty and a Dad Kitty to be cooled off
2427
//!
25-
//! In order to submit a valid transaction you must strutucture it as follows:
28+
//! In order to submit a valid transaction you must structure it as follows:
2629
//! 1.) Input must contain 1 mom and 1 dad
2730
//! 2.) Output must contain Mom, Dad, and newly created Child
2831
//! 3.) A child's DNA is calculated by:
@@ -41,7 +44,7 @@ use sp_runtime::{
4144
traits::{BlakeTwo256, Hash as HashT},
4245
transaction_validity::TransactionPriority,
4346
};
44-
use sp_std::collections::btree_map::BTreeMap;
47+
use sp_std::collections::btree_set::BTreeSet; // For checking the uniqueness of input and output based on dna.
4548
use sp_std::prelude::*;
4649
use tuxedo_core::{
4750
dynamic_typing::{DynamicallyTypedData, UtxoData},
@@ -53,6 +56,10 @@ use tuxedo_core::{
5356
#[cfg(test)]
5457
mod tests;
5558

59+
/// The main constraint checker for the kitty piece. Allows below :
60+
/// Create : Allows creation of kitty without parents, Multiple kitties can be created in same txn.
61+
/// UpdateKittyName : Allows updating the name of the kitty s, Multiple kitty name can be updated in same txn.
62+
/// Breed : Allows breeding of kitty.
5663
#[derive(
5764
Serialize,
5865
Deserialize,
@@ -68,14 +75,15 @@ mod tests;
6875
TypeInfo,
6976
)]
7077
pub enum FreeKittyConstraintChecker {
71-
/// A transaction that creates kitty without parents.
78+
/// Txn that creates kitty without parents.Multiple kitties can be created at the same time.
7279
Create,
73-
/// A Transaction that updates kitty Name.
80+
/// Txn that updates kitty Name. Multiple kitty names can be updated. input & output must follow the same order.
7481
UpdateKittyName,
75-
/// A transaction where kitties are consumed and new family(Parents(mom,dad) and child) is created.
82+
/// Txn where kitties are consumed and new family(Parents(mom,dad) and child) is created.
7683
Breed,
7784
}
7885

86+
/// Dad kitty status with respect to breeding.
7987
#[derive(
8088
Serialize,
8189
Deserialize,
@@ -93,10 +101,13 @@ pub enum FreeKittyConstraintChecker {
93101
)]
94102
pub enum DadKittyStatus {
95103
#[default]
104+
/// Can breed.
96105
RearinToGo,
106+
/// Can't breed due to tired.
97107
Tired,
98108
}
99109

110+
/// Mad kitty status with respect to breeding.
100111
#[derive(
101112
Serialize,
102113
Deserialize,
@@ -114,10 +125,13 @@ pub enum DadKittyStatus {
114125
)]
115126
pub enum MomKittyStatus {
116127
#[default]
128+
/// Can breed.
117129
RearinToGo,
130+
/// Can't breed due to recent child kitty delivery.
118131
HadBirthRecently,
119132
}
120133

134+
/// Parent stuct contains 1 mom kitty and 1 dad kitty.
121135
#[derive(
122136
Serialize,
123137
Deserialize,
@@ -170,6 +184,12 @@ impl Default for Parent {
170184
)]
171185
pub struct KittyDNA(pub H256);
172186

187+
/// Kitty data contains basic informationsuch as below :
188+
/// parent: 1 mom kitty and 1 dad kitty.
189+
/// free_breedings: Free breeding allowed on a kitty.
190+
/// dna :Its a unique per kitty.
191+
/// num_breedings: number of free breedings are remaining.
192+
/// name: Name of kitty.
173193
#[derive(
174194
Serialize,
175195
Deserialize,
@@ -233,6 +253,7 @@ impl UtxoData for KittyData {
233253
const TYPE_ID: [u8; 4] = *b"Kitt";
234254
}
235255

256+
/// Reasons that kitty opertaion may go wrong.
236257
#[derive(
237258
Serialize,
238259
Deserialize,
@@ -293,8 +314,10 @@ pub enum ConstraintCheckerError {
293314
CreatingWithInputs,
294315
/// No input for kitty Update.
295316
InvalidNumberOfInputOutput,
296-
/// Updating nothing
297-
OutputUtxoMissingError,
317+
/// Duplicate kitty found i.e based on the DNA.
318+
DuplicateKittyFound,
319+
/// Dna mismatch between input and output.
320+
DnaMismatchBetweenInputAndOutput,
298321
/// Name is not updated
299322
KittyNameUnAltered,
300323
/// Kitty FreeBreeding cannot be updated.
@@ -593,8 +616,8 @@ impl SimpleConstraintChecker for FreeKittyConstraintChecker {
593616

594617
/// Checks:
595618
/// - Input and output is of kittyType
596-
/// - Only name is updated and ther basicproperties are not updated.
597-
///
619+
/// - Only name is updated and ther basic properties are not updated.
620+
/// - Order between input and output must be same.
598621
pub fn can_kitty_name_be_updated(
599622
input_data: &[DynamicallyTypedData],
600623
output_data: &[DynamicallyTypedData],
@@ -603,34 +626,35 @@ pub fn can_kitty_name_be_updated(
603626
input_data.len() == output_data.len() && !input_data.is_empty(),
604627
{ ConstraintCheckerError::InvalidNumberOfInputOutput }
605628
);
629+
let mut dna_to_kitty_set: BTreeSet<KittyDNA> = BTreeSet::new();
606630

607-
let mut map: BTreeMap<KittyDNA, KittyData> = BTreeMap::new();
608-
609-
for utxo in input_data {
610-
let utxo_kitty = utxo
631+
for i in 0..input_data.len() {
632+
let utxo_input_kitty = input_data[i]
633+
.clone()
611634
.extract::<KittyData>()
612635
.map_err(|_| ConstraintCheckerError::BadlyTyped)?;
613-
map.insert(utxo_kitty.clone().dna, utxo_kitty);
614-
}
615636

616-
for utxo in output_data {
617-
let utxo_output_kitty = utxo
637+
if dna_to_kitty_set.contains(&utxo_input_kitty.dna) {
638+
return Err(ConstraintCheckerError::DuplicateKittyFound);
639+
} else {
640+
dna_to_kitty_set.insert(utxo_input_kitty.clone().dna);
641+
}
642+
643+
let utxo_output_kitty = output_data[i]
644+
.clone()
618645
.extract::<KittyData>()
619646
.map_err(|_| ConstraintCheckerError::BadlyTyped)?;
620-
621-
if let Some(input_kitty) = map.remove(&utxo_output_kitty.dna) {
622-
// Element found, access the value
623-
check_kitty_name_update(&input_kitty, &utxo_output_kitty)?;
624-
} else {
625-
return Err(ConstraintCheckerError::OutputUtxoMissingError);
647+
if utxo_input_kitty.dna != utxo_output_kitty.dna {
648+
return Err(ConstraintCheckerError::DnaMismatchBetweenInputAndOutput);
626649
}
650+
check_kitty_name_update(&utxo_input_kitty, &utxo_output_kitty)?;
627651
}
628652
return Ok(0);
629653
}
630654

631655
/// Checks:
632656
/// - Private function used by can_kitty_name_be_updated.
633-
/// - Only name is updated and ther basicproperties are not updated.
657+
/// - Only name is updated and ther basic properties are not updated.
634658
///
635659
fn check_kitty_name_update(
636660
original_kitty: &KittyData,

wardrobe/kitties/src/tests.rs

+41-4
Original file line numberDiff line numberDiff line change
@@ -628,17 +628,54 @@ fn update_name_dna_update_fails() {
628628
output.dna = KittyDNA(H256::from_slice(b"superkalifragislisticexpialadoca"));
629629
output.name = *b"kty1";
630630

631-
let input1 = KittyData::default_dad();
631+
let result = FreeKittyConstraintChecker::check(
632+
&FreeKittyConstraintChecker::UpdateKittyName,
633+
&[input.into()],
634+
&[],
635+
&[output.into()],
636+
);
637+
assert_eq!(
638+
result,
639+
Err(ConstraintCheckerError::DnaMismatchBetweenInputAndOutput)
640+
);
641+
}
642+
643+
#[test]
644+
fn update_name_duplicate_dna_update_fails() {
645+
let input = KittyData::default_dad();
646+
let mut output = input.clone();
647+
output.name = *b"kty1";
648+
649+
let result = FreeKittyConstraintChecker::check(
650+
&FreeKittyConstraintChecker::UpdateKittyName,
651+
&[input.clone().into(), input.into()],
652+
&[],
653+
&[output.clone().into(), output.into()],
654+
);
655+
assert_eq!(result, Err(ConstraintCheckerError::DuplicateKittyFound));
656+
}
657+
658+
#[test]
659+
fn update_name_out_of_order_input_and_output_fails() {
660+
let input = KittyData::default_dad();
661+
let mut output = input.clone();
662+
output.name = *b"kty1";
663+
664+
let mut input1 = KittyData::default_dad();
665+
input1.dna = KittyDNA(H256::from_slice(b"superkalifragislisticexpialadoca"));
632666
let mut output1 = input1.clone();
633667
output1.name = *b"kty2";
634668

635669
let result = FreeKittyConstraintChecker::check(
636670
&FreeKittyConstraintChecker::UpdateKittyName,
637-
&[input1.into(), input.into()],
671+
&[input.clone().into(), input1.into()],
638672
&[],
639-
&[output1.into(), output.into()],
673+
&[output1.clone().into(), output.into()],
674+
);
675+
assert_eq!(
676+
result,
677+
Err(ConstraintCheckerError::DnaMismatchBetweenInputAndOutput)
640678
);
641-
assert_eq!(result, Err(ConstraintCheckerError::OutputUtxoMissingError));
642679
}
643680

644681
#[test]

0 commit comments

Comments
 (0)