[r2r] broadcast tx to txhlp / refactor tx errors#1245
Conversation
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
0a6d0c9 to
43862b6
Compare
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: Onur Özkan <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
artemii235
left a comment
There was a problem hiding this comment.
Thanks for the prompt implementation! It's the first review iteration 🙂
| }, | ||
| }; | ||
|
|
||
| broadcast_transaction_message( |
There was a problem hiding this comment.
I have noticed that it's better to broadcast_transaction_message also if send_taker_refunds_payment and other fns fail. Please make send_taker_refunds_payment and others to also return the generated transaction in case of error and call broadcast_transaction_message for it.
There was a problem hiding this comment.
trait SwapOps functions are (only TransactionFut returners) now calling broadcast_transaction_message right after generating transaction.
There was a problem hiding this comment.
I'm a little confused 😅
Could you please tell where trait SwapOps functions call broadcast_transaction_message? I couldn't find it in the changes
There was a problem hiding this comment.
I'm a little confused sweat_smile Could you please tell where
trait SwapOpsfunctions callbroadcast_transaction_message? I couldn't find it in the changes
Sorry, I couldn't explain correctly. I didn't call broadcast_transaction_messageinside of the trait SwapOps functions, I call it in maker_swap and taker_swap after each trait SwapOps functions. But I guess Artem is pointing different thing than what I did here. I will update the changes today.
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
…slp_htlc_should_fail` Signed-off-by: ozkanonur <work@onurozkan.dev>
| let err = fusd.send_raw_tx(&tx_bytes_str).wait().unwrap_err(); | ||
| println!("{:?}", err); | ||
| assert!(err.contains("is not valid with reason outputs greater than inputs")); | ||
| assert!(err.contains("the transaction was rejected by network rules.\\n\\ntransaction already in block chain")); |
There was a problem hiding this comment.
This had to change since send_raw_tx now calling uxto_common::send_raw_tx here @artemii235
There was a problem hiding this comment.
@ozkanonur Very good that we have this test 🙂
I forgot that SLP requires additional transaction validation and provided incorrect comment that utxo_common::send_raw_tx_bytes can be used for it. Due to the missing validation, the invalid transaction was broadcast - with SLP protocol, it effectively means tokens burning (luckily, test net tokens in this case). More info on the topic: https://slp.dev/guides/slp-implementation-instructions/#have-multiple-sources-of-validation-or-client-side-validation
The usage of validation code
https://github.com/KomodoPlatform/atomicDEX-API/blob/ff6fc9f6722cf4f8ac0a290043deded201e7dc59/mm2src/coins/utxo/slp.rs#L1037-L1040
Could you please roll back the send_raw_tx implementation and use broadcast_tx in the Slp::send_raw_tx_bytes too? Please also extend this test and check that send_raw_tx_bytes will return is not valid with reason outputs greater than inputs for this tx.
Also, if the test started to fail, it's undesirable to change it - there's a very high chance that tested code got broken.
There was a problem hiding this comment.
Also, if the test started to fail, it's undesirable to change it - there's a very high chance that tested code got broken.
PS, even if I asked to change the code on the review 🙂 I can be wrong.
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
sergeyboyko0791
left a comment
There was a problem hiding this comment.
Great progress! Please take a look at my suggestions
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: Onur Özkan <work@onurozkan.dev>
There was a problem hiding this comment.
I think we need to send the P2P message when broadcasting lightning-related transactions too. The message broadcasting should be added to this function https://github.com/KomodoPlatform/atomicDEX-API/blob/5c24769605a3ce7ea6c336ffff7aeec351e7705c/mm2src/coins/lightning/ln_rpc.rs#L63
Need |
I see, then I guess I better handle this case once this PR is merged since I changed the implementation of the |
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
Signed-off-by: Onur Özkan <work@onurozkan.dev>
artemii235
left a comment
There was a problem hiding this comment.
I've noticed that few changes do not meet the initial requirement 🙂
Signed-off-by: ozkanonur <work@onurozkan.dev>
|
Waiting for @sergeyboyko0791 approval. |
sergeyboyko0791
left a comment
There was a problem hiding this comment.
Sorry for the late review.
It may take some time to consider my suggestions, please ping me when it's ready for the next review iteration.
| Box::new( | ||
| self.send_to_address(address, try_fus!(wei_from_big_decimal(&amount, self.decimals))) | ||
| self.send_to_address(address, try_tx_fus!(wei_from_big_decimal(&amount, self.decimals))) | ||
| .map_err(TransactionErr::PlainError) |
There was a problem hiding this comment.
EthCoin::send_to_address should return TransactionErr::TxRecoverableError. Please look at the sign_and_send_transaction_impl function:
https://github.com/KomodoPlatform/atomicDEX-API/blob/c23b1f7bb2941b51297709aee3ac3c46f5370c6f/mm2src/coins/eth.rs#L1382
| let signed = try_tx_fus!(SignedEthTx::new(tx)); | ||
| let swap_contract_address = try_tx_fus!(swap_contract_address.try_to_address()); |
There was a problem hiding this comment.
What do you think, should we return TransactionErr::TxRecoverableError if swap_contract_address.try_to_address() fails?
Please also check if we should do that in other places.
There was a problem hiding this comment.
I think we should, why not if we can just return it right?
|
|
||
| if now_ms() / 1000 > wait_until { | ||
| return ERR!( | ||
| return TX_ERR!( |
There was a problem hiding this comment.
It seems that TX_ERR returns TransactionErr::PlainError. So what do you think about renaming it to TX_PLAIN_ERR?
Also I'd suggest using snake_case for macros. I know that we use ERR a lot, so that there is no confusion, we can leave it as SCREAMING_SNAKE_CASE. I leave it up to you :)
There was a problem hiding this comment.
I agree, macros normally have snake_case naming convention, but here we are providing a compatibility for a macro that is already exists. We have to change all of them to avoid confusion(which we will do for #1247 ).
| } | ||
| } | ||
|
|
||
| pub type TransactionFut = Box<dyn Future<Item = TransactionEnum, Error = TransactionErr> + Send>; |
There was a problem hiding this comment.
Could you please consider this comment? #1258 (comment)
If you have a different point of view, I'll accept it 🙂
There was a problem hiding this comment.
I think both ways are fine. Declaring on top of the module or just keep them close to it's couples. But, have to apply only one of them in the project, otherwise it will complicate things more.
@artemii235 which way we should follow? The choice will effect all the project (either all the types will move to the top, or will move to it's couple structs/functions).
| } | ||
|
|
||
| impl MmCoinEnum { | ||
| pub fn is_utxo_and_in_native_mode(&self) -> bool { |
There was a problem hiding this comment.
Should it be is_utxo_in_native_mode instead?
There was a problem hiding this comment.
Should it be
is_utxo_in_native_modeinstead?
Yeah, damn what was I thinking 🤣
| return Err(TransactionErr::TxRecoverableError( | ||
| TransactionEnum::from(signed), | ||
| ERRL!("{:?}", err), |
There was a problem hiding this comment.
How about using a macro like:
/// `TransactionErr:TxRecoverableError` compatible `ERR` macro.
macro_rules! TX_RECOVERABLE_ERR {
($tx: expr, $format: expr, $($args: tt)+) => {
Err(crate::TransactionErr::TxRecoverableError(TransactionEnum::from($tx), ERRL!($format, $($args)+)))
};
($tx: expr, $format: expr) => {
Err(crate::TransactionErr::TxRecoverableError(TransactionEnum::from($tx), ERRL!($format)))
}
}This macro can be used elsewhere
There was a problem hiding this comment.
Yeah that's actually very good idea
| @@ -1083,10 +1100,15 @@ impl MarketCoinOps for Qrc20Coin { | |||
| from_block: u64, | |||
| _swap_contract_address: &Option<BytesJson>, | |||
| ) -> TransactionFut { | |||
There was a problem hiding this comment.
I think that the MarketCoinOps::wait_for_tx_spend method shouldn't return TransactionErr because it actually doesn't broadcast any transaction to the blockchain network.
I'd add another Transaction future that returns String error instead of TransactionErr.
It's only my opinion, so it's up to you to change or not
There was a problem hiding this comment.
I can rename TransactionErr into TransactionFutErr to make it more general. In this case, you don't need to create another error type since we can use TransactionFutErr::Plain. Is this okay for you?
There was a problem hiding this comment.
I think TransactionErr fits better, because we have functions that don't return futures.
I'd rather have TransactionFut = Box<dyn Future<Item = TransactionEnum, Error = String>> and TxRecoverableFut = Box<dyn Future<Item = TransactionEnum, Error = TransactionFutErr>>.
What do you think?
There was a problem hiding this comment.
But on the other hand, it may lead to confusion in macros, because try_tx_fus will actually return TxRecoverableFut. So, as I said, it's up to you :)
Signed-off-by: ozkanonur <work@onurozkan.dev>
|
@sergeyboyko0791 ready another iteration :) |
Signed-off-by: ozkanonur <work@onurozkan.dev>
sergeyboyko0791
left a comment
There was a problem hiding this comment.
Thanks for the fixes! Second review iteration
| key_pair.private().secret.as_slice(), | ||
| ); | ||
| let tx = try_s!(tx_fut.await); | ||
| let tx = try_tx_s!(tx_fut.await); |
There was a problem hiding this comment.
Shouldn't z_p2sh_spend return TransactionFutErr?
There was a problem hiding this comment.
Sorry, I didn't understand what exactly you mean here, it's already returning TransactionFutErr.
There was a problem hiding this comment.
I meant that z_p2sh_spend currently returns ZP2SHSpendError, but it could return an error extended by the TxRecoverable variant or something like that. It actually can return here
https://github.com/KomodoPlatform/atomicDEX-API/blob/5ba0dd1684ce879b4724c6c9badcbe524537f228/mm2src/coins/z_coin/z_htlc.rs#L164-L167
So maybe we can add ZP2SHSpendError::TxRecoverable 🤔
There was a problem hiding this comment.
I meant that
z_p2sh_spendcurrently returnsZP2SHSpendError, but it could return an error extended by theTxRecoverablevariant or something like that. It actually can return hereSo maybe we can add
ZP2SHSpendError::TxRecoverable
Implemented it now.
@artemii235 I can rollback the commit if this isn't necessary.
| Ok(Some(FoundSwapTxSpend::Spent(_))) => { | ||
| log!("Warning: MakerPayment spent, but TakerPayment is not yet. Trying to spend TakerPayment"); | ||
| let transaction = try_s!(try_spend_taker_payment(self, &secret_hash.0).await); | ||
|
|
There was a problem hiding this comment.
One question to the MakerSwap::recover_funds method - should we broadcast tx message in this case?
There was a problem hiding this comment.
We can't since try_spend_taker_payment doesn't' return recoverable tx.
There was a problem hiding this comment.
I couldn't comment on this snippet:
https://github.com/KomodoPlatform/atomicDEX-API/blob/f87cef3ba6d7802fcb720e4a69e43c27f653e14b/mm2src/lp_swap/maker_swap.rs#L1110-L1122
So I left the link
What do you think about send_maker_spends_taker_payment?
Signed-off-by: Onur Özkan <work@onurozkan.dev>
Signed-off-by: ozkanonur <work@onurozkan.dev>
sergeyboyko0791
left a comment
There was a problem hiding this comment.
A few minor changes please 🙂
Also I've noticed that swap methods can be refactored with MmError, so we could avoid adding some macros. But it's overhead for this PR, so let's plan to refactor them someday later.
|
|
||
| /// `TransactionFutErr:Plain` compatible `ERR` macro. | ||
| /// `ZP2SHSpendError` compatible `TransactionErr` handling macro. | ||
| macro_rules! try_ztx_s { |
There was a problem hiding this comment.
I think it's better to move the macro to z_coin.rs since it's compatible to ZCoin only. What do you think?
| return Err(crate::TransactionErr::Plain(format!( | ||
| "{}:{}] {:?}", | ||
| file!(), | ||
| line!(), | ||
| err |
There was a problem hiding this comment.
It can be simplified as:
return Err(crate::TransactionErr::Plain(ERRL!("{:?}", err)))| @@ -458,11 +458,8 @@ impl Qrc20Coin { | |||
| .generate_qrc20_transaction(outputs) | |||
| .await | |||
| .mm_err(|e| e.into_withdraw_error(platform, decimals)) | |||
There was a problem hiding this comment.
Could you please replace mm_err with map_err here? The error trace is collected on the line below
.map_err(|e| TransactionErr::Plain(ERRL!("{}", e)))?;So there is no need to convert the error to MmError.
Signed-off-by: Onur Özkan <work@onurozkan.dev>
I think this PR is already on the overhead stage so yeah it would be better to seperate refactoring tasks to another PR. 🙂 Fixed the notes. |
TransactionFut's error type(to recover transactions in some error cases.).TransactionErr::TxRecoverableErrortxhlp/TICKERP2P subscription when UTXO coins are activated in native mode.