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

feat(trading-proto-upgrade): UTXO PoC + State machine refactor #1927

Merged
merged 31 commits into from
Aug 23, 2023

Conversation

artemii235
Copy link
Member

  • Added SwapOpsV2 trait containing methods of the new protocol (WIP).
  • Implemented SwapOpsV2 for UtxoStandardCoin.
  • Added dockerized integration tests, sending and spending/refunding "dex fee + premium" UTXO.
  • Refactored state machine as a preparation step for StorableStateMachine pattern extension.

#1895

Copy link
Member

@onur-ozkan onur-ozkan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huge work!

First review(roughly) iteration from my side:

mm2src/mm2_main/src/lp_swap/taker_swap.rs Outdated Show resolved Hide resolved
mm2src/common/patterns/state_machine.rs Outdated Show resolved Hide resolved
mm2src/common/patterns/state_machine.rs Show resolved Hide resolved
mm2src/mm2_main/src/lp_swap/maker_swap.rs Outdated Show resolved Hide resolved
@artemii235
Copy link
Member Author

@ozkanonur Thanks for your review, all notes are fixed.

Copy link
Collaborator

@shamardy shamardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the great work! Only 2 suggestions/questions at this stage as I couldn't find any major issues in this first review. Will do another review later but everything seems good after first look :)

pub async fn validate_dex_fee_spend_preimage<T: UtxoCommonOps + SwapOps>(
coin: &T,
gen_args: &GenDexFeeSpendArgs<'_>,
preimage: &TxPreimageWithSig,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the signature enough to be shared in P2P messages? I think there is no need to share and validate the preimage since it can be constructed at the maker side. If that is the case, this can be done in next PRs.

Copy link
Member Author

@artemii235 artemii235 Aug 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In UTXO case, maker can get a different transaction lock time and resulting premium amount (depending on miner fee). So, I had to add LocktimeSetting and CalcPremiumBy enums, and use the exact values from taker's preimage on maker's side. For other coin protocols, only signature might be sufficient.

let expected_preimage = gen_dex_fee_spend_preimage(
coin,
gen_args,
LocktimeSetting::UseExact(actual_preimage_tx.lock_time),
CalcPremiumBy::UseExactAmount(actual_preimage_tx.outputs[1].value),
)
.await?;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For other coin protocols, only signature might be sufficient.

Thanks for the explanation. I guess miner fee/gas discrepancy can also make signature not enough for other coins since they are part of the signed transaction. Can a different SIGHASH be used to allow bob decide the miner fee they want to pay instead of verifying the fee that alice calculated?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For ETH/ERC-20, transaction preimage signing won't be required. Taker will sign a payload that will specify shares and destinations to which the payment should be spent. Maker will add the signature as an argument to smart contract call. For other protocols, additional research is required.

Can a different SIGHASH be used to allow bob decide the miner fee they want to pay instead of verifying the fee that alice calculated?

I will check it on next iterations, thanks for the idea!

mm2src/coins/utxo/utxo_common.rs Show resolved Hide resolved
@artemii235 artemii235 mentioned this pull request Jul 3, 2023
23 tasks
Copy link
Member

@onur-ozkan onur-ozkan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last review iteration:

coin,
gen_args,
LocktimeSetting::UseExact(actual_preimage_tx.lock_time),
CalcPremiumBy::UseExactAmount(actual_preimage_tx.outputs[1].value),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you use get to access indexes(including the other ones in this module)? It's panic-safe and allows us to handle out of bounds situations.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have fixed this line but preferred to keep other cases as is for now to not make the diff even larger. Added to checklist for next iteration: #1895 (comment)

coin.as_ref().conf.signature_version,
coin.as_ref().conf.fork_id
));
let sig_hash_all_fork_id = 1 | coin.as_ref().conf.fork_id as u8;
Copy link
Member

@onur-ozkan onur-ozkan Aug 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: Are we 100% sure that fork_id in coins configuration is always <= u8::MAX? Otherwise sig_hash_all_fork_id may have unexpected/random values.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no such validation and coins repo even has asset using 2 bytes value for fork_id:
https://github.com/KomodoPlatform/coins/blob/05eb26c9fdecb6168f4d900fa2db7464ddd6b675/coins#L7229.
I am now wondering whether this LTFN coin works at all 🙂

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UPD: at least it used to work at the moment of addition: KomodoPlatform/coins@676149e.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem of using as is sometimes it returns random values when overflow occurs which may result in unexpected behaviours and it's really hard to catch.

AFAIK fork_id is currently u32. If we update it to u8, it will make more sense to use it fork_id as u32 which can't overflow so there will be no unexpected behaviour. And if a longer value than u8 was given to fork_id in coins config, mm2 will validate and panic the process automatically on the initialization

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trick with forementioned LTFN coin is it already uses 0x2A40 fork_id that doesn't fit into u8, and it somehow worked with as u8 conversion, which is actually used for a long time in our signing code:

sig_script.append(&mut Bytes::from(vec![1 | fork_id as u8]));

I will need some time to do research on this, as it looks strange.

Comment on lines +4606 to +4611
if dex_fee_tx.outputs[0] != expected_output {
return MmError::err(ValidateDexFeeError::InvalidDestinationOrAmount(format!(
"Expected {:?}, got {:?}",
expected_output, dex_fee_tx.outputs[0]
)));
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if dex_fee_tx.outputs[0] != expected_output {
return MmError::err(ValidateDexFeeError::InvalidDestinationOrAmount(format!(
"Expected {:?}, got {:?}",
expected_output, dex_fee_tx.outputs[0]
)));
}
if dex_fee_tx.outputs.first() != Some(&expected_output) {
return MmError::err(ValidateDexFeeError::InvalidDestinationOrAmount(format!(
"Expected {:?}, got {:?}",
expected_output, dex_fee_tx.outputs.first()
)));
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As outputs' length is checked previously, is this really required?

if dex_fee_tx.outputs.len() < 2 {
return MmError::err(ValidateDexFeeError::TxLacksOfOutputs);
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As outputs' length is checked previously, is this really required?

I missed that on the review. At this point it's not required, but still safer way to follow in my opinion(e.g., when a dev makes changes here will likely forget updating the following parts of codes since it's not easy to catch). You can keep it or update it, I leave it to you

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I will update it in the next iteration - we can change the number of outputs in the future, and as you said, forget to update relevant parts of the code. Using get(index) will be safer in general.

@artemii235 artemii235 changed the title feat(trading-proto-upgrade): UTXO PoC + State machine refactor feat(trading-proto-upgrade): UTXO PoC and State machine refactor Aug 14, 2023
@artemii235 artemii235 changed the title feat(trading-proto-upgrade): UTXO PoC and State machine refactor feat(trading-proto-upgrade): UTXO PoC + State machine refactor Aug 14, 2023
@artemii235 artemii235 changed the title feat(trading-proto-upgrade): UTXO PoC + State machine refactor feat(trading-proto-upgrade): uTXO PoC + State machine refactor Aug 14, 2023
@artemii235 artemii235 changed the title feat(trading-proto-upgrade): uTXO PoC + State machine refactor feat(trading-proto-upgrade): UTXO PoC + State machine refactor Aug 14, 2023
Copy link
Collaborator

@shamardy shamardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀

Copy link
Collaborator

@dimxy dimxy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used this review mostly for studying code

@shamardy shamardy merged commit 483f04c into dev Aug 23, 2023
0 of 2 checks passed
@shamardy shamardy deleted the swap-proto-upgrade-iteration-1 branch August 23, 2023 11:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants