-
Notifications
You must be signed in to change notification settings - Fork 19
TradableKitty piece
#171
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
base: main
Are you sure you want to change the base?
TradableKitty piece
#171
Changes from 7 commits
b522b1b
2e0885d
80d2e99
5461173
eea8241
1f5855b
4d4501b
32be05f
7b0a12e
389576b
c77120b
d57f9b1
db5748d
02aaf78
9c4f903
9e2c908
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,12 +1,31 @@ | ||||||||||||||||||||||||||||||||||
| //! An NFT game inspired by cryptokitties. | ||||||||||||||||||||||||||||||||||
| //! This is a game which allows for kitties to be bred based on a few factors | ||||||||||||||||||||||||||||||||||
| //! 1.) Mom and Tired have to be in a state where they are ready to breed | ||||||||||||||||||||||||||||||||||
| //! This is a game which allows for kitties to be create,bred and update name of kitty. | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! ## Features | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! - **Create:** Generate a new kitty. | ||||||||||||||||||||||||||||||||||
| //! To submit a valid transaction for creating a kitty, adhere to the following structure: | ||||||||||||||||||||||||||||||||||
|
muraca marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||
| //! 1. Input must be empty. | ||||||||||||||||||||||||||||||||||
| //! 2. Output must contain only the newly created kittities as a child. | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! **Note 1:** Multiple kitties can be created at the same time in the same txn.. | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! - **Update Name:** Modify the name of a kitty. | ||||||||||||||||||||||||||||||||||
| //! To submit a valid transaction for updating a kitty's name, adhere to the following structure: | ||||||||||||||||||||||||||||||||||
| //! 1. Input must be the kitty to be updated. | ||||||||||||||||||||||||||||||||||
| //! 2. Output must contain the kitty with the updated name. | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! **Note 1:** All other properties such as DNA, parents, free breedings, etc., must remain unaltered in the output. | ||||||||||||||||||||||||||||||||||
| //! **Note 2:** The input and output kitties must follow same order. | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! - **Breed:** Breeds a new kitty using mom and dad based on below factors | ||||||||||||||||||||||||||||||||||
| //! 1.) Mom and Dad have to be in a state where they are ready to breed | ||||||||||||||||||||||||||||||||||
| //! 2.) Each Mom and Dad have some DNA and the child will have unique DNA combined from the both of them | ||||||||||||||||||||||||||||||||||
| //! Linkable back to the Mom and Dad | ||||||||||||||||||||||||||||||||||
| //! 3.) The game also allows Kitties to have a cooling off period inbetween breeding before they can be bred again. | ||||||||||||||||||||||||||||||||||
| //! 4.) A rest operation allows for a Mom Kitty and a Dad Kitty to be cooled off | ||||||||||||||||||||||||||||||||||
| //! | ||||||||||||||||||||||||||||||||||
| //! In order to submit a valid transaction you must strutucture it as follows: | ||||||||||||||||||||||||||||||||||
| //! In order to submit a valid transaction you must structure it as follows: | ||||||||||||||||||||||||||||||||||
|
muraca marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||
| //! 1.) Input must contain 1 mom and 1 dad | ||||||||||||||||||||||||||||||||||
| //! 2.) Output must contain Mom, Dad, and newly created Child | ||||||||||||||||||||||||||||||||||
| //! 3.) A child's DNA is calculated by: | ||||||||||||||||||||||||||||||||||
|
|
@@ -25,6 +44,7 @@ use sp_runtime::{ | |||||||||||||||||||||||||||||||||
| traits::{BlakeTwo256, Hash as HashT}, | ||||||||||||||||||||||||||||||||||
| transaction_validity::TransactionPriority, | ||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||
| use sp_std::collections::btree_set::BTreeSet; // For checking the uniqueness of input and output based on dna. | ||||||||||||||||||||||||||||||||||
| use sp_std::prelude::*; | ||||||||||||||||||||||||||||||||||
| use tuxedo_core::{ | ||||||||||||||||||||||||||||||||||
| dynamic_typing::{DynamicallyTypedData, UtxoData}, | ||||||||||||||||||||||||||||||||||
|
|
@@ -36,6 +56,10 @@ use tuxedo_core::{ | |||||||||||||||||||||||||||||||||
| #[cfg(test)] | ||||||||||||||||||||||||||||||||||
| mod tests; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| /// The main constraint checker for the kitty piece. Allows below : | ||||||||||||||||||||||||||||||||||
| /// Create : Allows creation of kitty without parents, Multiple kitties can be created in same txn. | ||||||||||||||||||||||||||||||||||
| /// UpdateKittyName : Allows updating the name of the kitty s, Multiple kitty name can be updated in same txn. | ||||||||||||||||||||||||||||||||||
| /// Breed : Allows breeding of kitty. | ||||||||||||||||||||||||||||||||||
| #[derive( | ||||||||||||||||||||||||||||||||||
| Serialize, | ||||||||||||||||||||||||||||||||||
| Deserialize, | ||||||||||||||||||||||||||||||||||
|
|
@@ -50,8 +74,16 @@ mod tests; | |||||||||||||||||||||||||||||||||
| Debug, | ||||||||||||||||||||||||||||||||||
| TypeInfo, | ||||||||||||||||||||||||||||||||||
| )] | ||||||||||||||||||||||||||||||||||
| pub struct FreeKittyConstraintChecker; | ||||||||||||||||||||||||||||||||||
| pub enum FreeKittyConstraintChecker { | ||||||||||||||||||||||||||||||||||
| /// Txn that creates kitty without parents.Multiple kitties can be created at the same time. | ||||||||||||||||||||||||||||||||||
| Create, | ||||||||||||||||||||||||||||||||||
| /// Txn that updates kitty Name. Multiple kitty names can be updated. input & output must follow the same order. | ||||||||||||||||||||||||||||||||||
| UpdateKittyName, | ||||||||||||||||||||||||||||||||||
| /// Txn where kitties are consumed and new family(Parents(mom,dad) and child) is created. | ||||||||||||||||||||||||||||||||||
| Breed, | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| /// Dad kitty status with respect to breeding. | ||||||||||||||||||||||||||||||||||
| #[derive( | ||||||||||||||||||||||||||||||||||
| Serialize, | ||||||||||||||||||||||||||||||||||
| Deserialize, | ||||||||||||||||||||||||||||||||||
|
|
@@ -69,10 +101,13 @@ pub struct FreeKittyConstraintChecker; | |||||||||||||||||||||||||||||||||
| )] | ||||||||||||||||||||||||||||||||||
| pub enum DadKittyStatus { | ||||||||||||||||||||||||||||||||||
| #[default] | ||||||||||||||||||||||||||||||||||
| /// Can breed. | ||||||||||||||||||||||||||||||||||
| RearinToGo, | ||||||||||||||||||||||||||||||||||
| /// Can't breed due to tired. | ||||||||||||||||||||||||||||||||||
|
muraca marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||
| Tired, | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| /// Mad kitty status with respect to breeding. | ||||||||||||||||||||||||||||||||||
| #[derive( | ||||||||||||||||||||||||||||||||||
| Serialize, | ||||||||||||||||||||||||||||||||||
| Deserialize, | ||||||||||||||||||||||||||||||||||
|
|
@@ -90,10 +125,13 @@ pub enum DadKittyStatus { | |||||||||||||||||||||||||||||||||
| )] | ||||||||||||||||||||||||||||||||||
| pub enum MomKittyStatus { | ||||||||||||||||||||||||||||||||||
| #[default] | ||||||||||||||||||||||||||||||||||
| /// Can breed. | ||||||||||||||||||||||||||||||||||
| RearinToGo, | ||||||||||||||||||||||||||||||||||
| /// Can't breed due to recent child kitty delivery. | ||||||||||||||||||||||||||||||||||
| HadBirthRecently, | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| /// Parent stuct contains 1 mom kitty and 1 dad kitty. | ||||||||||||||||||||||||||||||||||
| #[derive( | ||||||||||||||||||||||||||||||||||
| Serialize, | ||||||||||||||||||||||||||||||||||
| Deserialize, | ||||||||||||||||||||||||||||||||||
|
|
@@ -146,6 +184,12 @@ impl Default for Parent { | |||||||||||||||||||||||||||||||||
| )] | ||||||||||||||||||||||||||||||||||
| pub struct KittyDNA(pub H256); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| /// Kitty data contains basic informationsuch as below : | ||||||||||||||||||||||||||||||||||
| /// parent: 1 mom kitty and 1 dad kitty. | ||||||||||||||||||||||||||||||||||
| /// free_breedings: Free breeding allowed on a kitty. | ||||||||||||||||||||||||||||||||||
| /// dna :Its a unique per kitty. | ||||||||||||||||||||||||||||||||||
| /// num_breedings: number of free breedings are remaining. | ||||||||||||||||||||||||||||||||||
| /// name: Name of kitty. | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+185
to
+204
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From this comment, I can't understand how
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I will update it as below :
Earlier It was without any comments, So I decided to add it.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1 -> Number of free breedings allowed for the Kitty |
||||||||||||||||||||||||||||||||||
| #[derive( | ||||||||||||||||||||||||||||||||||
| Serialize, | ||||||||||||||||||||||||||||||||||
| Deserialize, | ||||||||||||||||||||||||||||||||||
|
|
@@ -165,6 +209,7 @@ pub struct KittyData { | |||||||||||||||||||||||||||||||||
| pub free_breedings: u64, // Ignore in breed for money case | ||||||||||||||||||||||||||||||||||
| pub dna: KittyDNA, | ||||||||||||||||||||||||||||||||||
| pub num_breedings: u128, | ||||||||||||||||||||||||||||||||||
| pub name: [u8; 4], | ||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, I think the fields should follow a more logical order, such as:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is generally better to add new members at the end of a struct. This practice aligns with the principle of maintaining backward compatibility. When we add a new member at the end of the struct, existing code that uses the struct won't be affected, as the layout of the existing members remains unchanged. If you add a new member in the middle of a struct, it can break existing code that relies on the order and size of the struct members. This is because the memory layout of the struct may change, leading to potential issues with code that assumes a specific order or size. By appending new members at the end, we follow a practice commonly referred to as "struct versioning" or "extensible struct pattern," where you ensure that new fields are added without affecting the existing layout. This helps in maintaining compatibility and minimizes the risk of introducing errors in the existing codebase. As of now, I don't see any code which is relying on the layout of the structure.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Although you are not wrong, at this stage of the development we don't need to care about this, and we should prioritize doing stuff that makes sense and is clear and understandable. And sometimes, you do want to break compatibility.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. I updated the struct as you suggested. |
||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| impl KittyData { | ||||||||||||||||||||||||||||||||||
|
|
@@ -187,7 +232,7 @@ impl KittyData { | |||||||||||||||||||||||||||||||||
| v, | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
| .into()], | ||||||||||||||||||||||||||||||||||
| checker: FreeKittyConstraintChecker.into(), | ||||||||||||||||||||||||||||||||||
| checker: FreeKittyConstraintChecker::Create.into(), | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
@@ -199,6 +244,7 @@ impl Default for KittyData { | |||||||||||||||||||||||||||||||||
| free_breedings: 2, | ||||||||||||||||||||||||||||||||||
| dna: KittyDNA(H256::from_slice(b"mom_kitty_1asdfasdfasdfasdfasdfa")), | ||||||||||||||||||||||||||||||||||
| num_breedings: 3, | ||||||||||||||||||||||||||||||||||
| name: *b"kity", | ||||||||||||||||||||||||||||||||||
|
NadigerAmit marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
@@ -207,6 +253,7 @@ impl UtxoData for KittyData { | |||||||||||||||||||||||||||||||||
| const TYPE_ID: [u8; 4] = *b"Kitt"; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| /// Reasons that kitty opertaion may go wrong. | ||||||||||||||||||||||||||||||||||
| #[derive( | ||||||||||||||||||||||||||||||||||
| Serialize, | ||||||||||||||||||||||||||||||||||
| Deserialize, | ||||||||||||||||||||||||||||||||||
|
|
@@ -261,9 +308,27 @@ pub enum ConstraintCheckerError { | |||||||||||||||||||||||||||||||||
| TooManyBreedingsForKitty, | ||||||||||||||||||||||||||||||||||
| /// Not enough free breedings available for these parents. | ||||||||||||||||||||||||||||||||||
| NotEnoughFreeBreedings, | ||||||||||||||||||||||||||||||||||
| /// The transaction attempts to create no Kitty. | ||||||||||||||||||||||||||||||||||
| CreatingNothing, | ||||||||||||||||||||||||||||||||||
| /// Inputs(Parents) not required for mint. | ||||||||||||||||||||||||||||||||||
| CreatingWithInputs, | ||||||||||||||||||||||||||||||||||
| /// No input for kitty Update. | ||||||||||||||||||||||||||||||||||
| InvalidNumberOfInputOutput, | ||||||||||||||||||||||||||||||||||
| /// Duplicate kitty found i.e based on the DNA. | ||||||||||||||||||||||||||||||||||
| DuplicateKittyFound, | ||||||||||||||||||||||||||||||||||
| /// Dna mismatch between input and output. | ||||||||||||||||||||||||||||||||||
| DnaMismatchBetweenInputAndOutput, | ||||||||||||||||||||||||||||||||||
| /// Name is not updated | ||||||||||||||||||||||||||||||||||
| KittyNameUnAltered, | ||||||||||||||||||||||||||||||||||
| /// Kitty FreeBreeding cannot be updated. | ||||||||||||||||||||||||||||||||||
| FreeBreedingCannotBeUpdated, | ||||||||||||||||||||||||||||||||||
| /// Kitty NumOfBreeding cannot be updated. | ||||||||||||||||||||||||||||||||||
| NumOfBreedingCannotBeUpdated, | ||||||||||||||||||||||||||||||||||
| /// Gender cannot be updated | ||||||||||||||||||||||||||||||||||
| KittyGenderCannotBeUpdated, | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| trait Breed { | ||||||||||||||||||||||||||||||||||
| pub trait Breed { | ||||||||||||||||||||||||||||||||||
| /// The Cost to breed a kitty if it is not free. | ||||||||||||||||||||||||||||||||||
| const COST: u128; | ||||||||||||||||||||||||||||||||||
| /// Number of free breedings a kitty will have. | ||||||||||||||||||||||||||||||||||
|
|
@@ -500,28 +565,116 @@ impl TryFrom<&DynamicallyTypedData> for KittyData { | |||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| impl SimpleConstraintChecker for FreeKittyConstraintChecker { | ||||||||||||||||||||||||||||||||||
| type Error = ConstraintCheckerError; | ||||||||||||||||||||||||||||||||||
| /// Checks: | ||||||||||||||||||||||||||||||||||
| /// - `input_data` is of length 2 | ||||||||||||||||||||||||||||||||||
| /// - `output_data` is of length 3 | ||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| fn check( | ||||||||||||||||||||||||||||||||||
| &self, | ||||||||||||||||||||||||||||||||||
| input_data: &[DynamicallyTypedData], | ||||||||||||||||||||||||||||||||||
| _peeks: &[DynamicallyTypedData], | ||||||||||||||||||||||||||||||||||
| output_data: &[DynamicallyTypedData], | ||||||||||||||||||||||||||||||||||
| ) -> Result<TransactionPriority, Self::Error> { | ||||||||||||||||||||||||||||||||||
| // Input must be a Mom and a Dad | ||||||||||||||||||||||||||||||||||
| ensure!(input_data.len() == 2, Self::Error::TwoParentsDoNotExist); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| let mom = KittyData::try_from(&input_data[0])?; | ||||||||||||||||||||||||||||||||||
| let dad = KittyData::try_from(&input_data[1])?; | ||||||||||||||||||||||||||||||||||
| KittyHelpers::can_breed(&mom, &dad)?; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| // Output must be Mom, Dad, Child | ||||||||||||||||||||||||||||||||||
| ensure!(output_data.len() == 3, Self::Error::NotEnoughFamilyMembers); | ||||||||||||||||||||||||||||||||||
| match &self { | ||||||||||||||||||||||||||||||||||
| Self::Create => { | ||||||||||||||||||||||||||||||||||
| // Make sure there are no inputs being consumed | ||||||||||||||||||||||||||||||||||
| ensure!( | ||||||||||||||||||||||||||||||||||
| input_data.is_empty(), | ||||||||||||||||||||||||||||||||||
| ConstraintCheckerError::CreatingWithInputs | ||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| // Make sure there is at least one output being minted | ||||||||||||||||||||||||||||||||||
| ensure!( | ||||||||||||||||||||||||||||||||||
| !output_data.is_empty(), | ||||||||||||||||||||||||||||||||||
| ConstraintCheckerError::CreatingNothing | ||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| // Make sure the outputs are the right type | ||||||||||||||||||||||||||||||||||
| for utxo in output_data { | ||||||||||||||||||||||||||||||||||
| let _utxo_kitty = utxo | ||||||||||||||||||||||||||||||||||
| .extract::<KittyData>() | ||||||||||||||||||||||||||||||||||
| .map_err(|_| ConstraintCheckerError::BadlyTyped)?; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| Ok(0) | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+586
to
+605
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we somehow check that a Kitty with the same DNA does not exist?
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is one of the reasons I didn't like minting kitties from scratch
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I raised this question earlier with Joshy and found that no need to check for duplicate DNA check since there can be twin kitties with duplicate DNA. So I removed the duplicate DNA check.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, we state in multiple parts of the documentation that DNA is unique 😄 As far as I remember, the twins use-case was not initially part of Kitties, what's the reason behind adding it? Moreover, twins in my opinion should not have the exact same DNA, as it is also in real life
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @muraca
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On a call recently, I encouraged @NadigerAmit to design the game fully before trying to build it and get a PR approved. Specifically I encouraged him to consider:
I don't think there are right vs wrong answers. But you need a design and you need to be consistent about it. I worry we reached a point where Amit feels very "close" to getting this PR merged, but I feel the design work isn't even done to compare the code against. |
||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| Self::Breed => { | ||||||||||||||||||||||||||||||||||
| // Check that we are consuming at least one input | ||||||||||||||||||||||||||||||||||
| ensure!(input_data.len() == 2, Self::Error::TwoParentsDoNotExist); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| let mom = KittyData::try_from(&input_data[0])?; | ||||||||||||||||||||||||||||||||||
| let dad = KittyData::try_from(&input_data[1])?; | ||||||||||||||||||||||||||||||||||
| KittyHelpers::can_breed(&mom, &dad)?; | ||||||||||||||||||||||||||||||||||
| // Output must be Mom, Dad, Child | ||||||||||||||||||||||||||||||||||
| ensure!(output_data.len() == 3, Self::Error::NotEnoughFamilyMembers); | ||||||||||||||||||||||||||||||||||
| KittyHelpers::check_new_family(&mom, &dad, output_data)?; | ||||||||||||||||||||||||||||||||||
| Ok(0) | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| Self::UpdateKittyName => { | ||||||||||||||||||||||||||||||||||
| can_kitty_name_be_updated(input_data, output_data)?; | ||||||||||||||||||||||||||||||||||
| Ok(0) | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| KittyHelpers::check_new_family(&mom, &dad, output_data)?; | ||||||||||||||||||||||||||||||||||
| /// Checks: | ||||||||||||||||||||||||||||||||||
| /// - Input and output is of kittyType | ||||||||||||||||||||||||||||||||||
| /// - Only name is updated and ther basic properties are not updated. | ||||||||||||||||||||||||||||||||||
| /// - Order between input and output must be same. | ||||||||||||||||||||||||||||||||||
| pub fn can_kitty_name_be_updated( | ||||||||||||||||||||||||||||||||||
| input_data: &[DynamicallyTypedData], | ||||||||||||||||||||||||||||||||||
| output_data: &[DynamicallyTypedData], | ||||||||||||||||||||||||||||||||||
| ) -> Result<TransactionPriority, ConstraintCheckerError> { | ||||||||||||||||||||||||||||||||||
| ensure!( | ||||||||||||||||||||||||||||||||||
| input_data.len() == output_data.len() && !input_data.is_empty(), | ||||||||||||||||||||||||||||||||||
| { ConstraintCheckerError::InvalidNumberOfInputOutput } | ||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||
| let mut dna_to_kitty_set: BTreeSet<KittyDNA> = BTreeSet::new(); | ||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems like you're spending a lot of effort making sure that no two kitties have the same DNA here. But isn't that already guaranteed (assuming polynomial time advarsaries) by the hash function itself? I recommend you remove this check entirely. Here you should just make sure that the output kitties are the same as the input kitties except for the names. If you aren't convinced, I challenge you to think of a case where two kitties would have the same DNA.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @JoshOrndorff, Thank you. I can remove those checks but I thought of below cases: Case1:
Blockchain logs: I truncated the logs manually for easy reading :
You can see I could create 2 kitties with 1 kitty by abusing update name API . So thought of preventing that with the Line no 647 to 649 i.e below : With the above check the transaction will fail as below: I removed some logs for easy reading .
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Case 2:
I did the below steps Below are the wallet logs Blockchain log: If I have the below line I can avoid this situation as inputs are checked. I checked the kitties via verifykitty which will get the kitties from the blockchain db, Then I also could fine 2 kitties with the same DNA.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I am doing something wrong in the above tests, Please suggest.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi Joshy, I have delved deeper into the issues and identified the root cause of why duplicate DNA can occur in kitties. Issue 1: Duplicate UTXO Checks Tuxedo/tuxedo-core/src/executive.rs Lines 110 to 125 in 1ad2343
Perhaps originally, the design intended to have a single output of the same type. Possible Solutions: Issue 2: DNA Calculation and Uniqueness This issue predominantly concerns kitties, and it remains unclear if it also applies to other UTXOs. Currently, Possible Solution: I think it is better to create new issues for this. I will do it
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've replied in your issue #190. I think you are not distinguishing between the concepts of two kitties with the same DNA vs a single kitty. You cannot input the same kitty twice because tuxedo core already checks it. The question here is how would you ever get two identical kitties to begin with. The only way is if you mint them directly. Up to you whether that is valid or not. If it is not, use a universal creator to ensure they are always unique. If it is valid to mint kitties with identical dna, then it should be no surprise that their offspring can also have identical DNA.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks @JoshOrndorff, I removed the DNA check. |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| for i in 0..input_data.len() { | ||||||||||||||||||||||||||||||||||
| let utxo_input_kitty = input_data[i] | ||||||||||||||||||||||||||||||||||
| .clone() | ||||||||||||||||||||||||||||||||||
|
NadigerAmit marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||
| .extract::<KittyData>() | ||||||||||||||||||||||||||||||||||
| .map_err(|_| ConstraintCheckerError::BadlyTyped)?; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if dna_to_kitty_set.contains(&utxo_input_kitty.dna) { | ||||||||||||||||||||||||||||||||||
| return Err(ConstraintCheckerError::DuplicateKittyFound); | ||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||
| dna_to_kitty_set.insert(utxo_input_kitty.clone().dna); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| Ok(0) | ||||||||||||||||||||||||||||||||||
| let utxo_output_kitty = output_data[i] | ||||||||||||||||||||||||||||||||||
| .clone() | ||||||||||||||||||||||||||||||||||
| .extract::<KittyData>() | ||||||||||||||||||||||||||||||||||
| .map_err(|_| ConstraintCheckerError::BadlyTyped)?; | ||||||||||||||||||||||||||||||||||
| if utxo_input_kitty.dna != utxo_output_kitty.dna { | ||||||||||||||||||||||||||||||||||
| return Err(ConstraintCheckerError::DnaMismatchBetweenInputAndOutput); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| check_kitty_name_update(&utxo_input_kitty, &utxo_output_kitty)?; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| return Ok(0); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| /// Checks: | ||||||||||||||||||||||||||||||||||
| /// - Private function used by can_kitty_name_be_updated. | ||||||||||||||||||||||||||||||||||
| /// - Only name is updated and ther basic properties are not updated. | ||||||||||||||||||||||||||||||||||
| /// | ||||||||||||||||||||||||||||||||||
| fn check_kitty_name_update( | ||||||||||||||||||||||||||||||||||
| original_kitty: &KittyData, | ||||||||||||||||||||||||||||||||||
| updated_kitty: &KittyData, | ||||||||||||||||||||||||||||||||||
| ) -> Result<TransactionPriority, ConstraintCheckerError> { | ||||||||||||||||||||||||||||||||||
| ensure!( | ||||||||||||||||||||||||||||||||||
| original_kitty != updated_kitty, | ||||||||||||||||||||||||||||||||||
| ConstraintCheckerError::KittyNameUnAltered | ||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||
| ensure!( | ||||||||||||||||||||||||||||||||||
| original_kitty.free_breedings == updated_kitty.free_breedings, | ||||||||||||||||||||||||||||||||||
| ConstraintCheckerError::FreeBreedingCannotBeUpdated | ||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||
| ensure!( | ||||||||||||||||||||||||||||||||||
| original_kitty.num_breedings == updated_kitty.num_breedings, | ||||||||||||||||||||||||||||||||||
| ConstraintCheckerError::NumOfBreedingCannotBeUpdated | ||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||
| ensure!( | ||||||||||||||||||||||||||||||||||
| original_kitty.parent == updated_kitty.parent, | ||||||||||||||||||||||||||||||||||
| ConstraintCheckerError::KittyGenderCannotBeUpdated | ||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+658
to
+677
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @JoshOrndorff do you think we should encourage this approach of multiple errors and verbosity?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe it is preferable to provide a more granular error message, specifying the reason for the issue. High-level errors like 'BasicPropertiesAltered' may not offer sufficient information to developers, especially when dealing with multiple properties, making it challenging to discern the exact nature of the problem.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not necessarily against this, but I think there should be some clear guidelines in Tuxedo, as sometimes we did the opposite
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't have an opinion. I'm fine to try it out this way and see what is better for downstream devs and end users. |
||||||||||||||||||||||||||||||||||
| return Ok(0); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.