-
Notifications
You must be signed in to change notification settings - Fork 74
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
WalletSwapCoin: Split into two classes + add trait #29
Conversation
Codecov Report
@@ Coverage Diff @@
## master #29 +/- ##
==========================================
- Coverage 80.83% 77.92% -2.91%
==========================================
Files 8 8
Lines 2588 2750 +162
==========================================
+ Hits 2092 2143 +51
- Misses 496 607 +111
Continue to review full report at Codecov.
|
Thanks for the PR(!) |
src/contracts.rs
Outdated
fn get_other_privkey(&self) -> Option<&SecretKey>; | ||
fn get_contract_privkey(&self) -> Option<&SecretKey>; | ||
fn get_hash_preimage(&self) -> Option<&[u8; 32]>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These functions should not be part of the trait SwapCoin.
Because WatchOnlySwapCoins will never have access to these, and our code ends up trying to get the hash preimage or contract privkey from a WatchOnlySwapCoin then the compiler should raise an error. I got the idea from this section https://doc.rust-lang.org/book/ch17-03-oo-design-patterns.html#encoding-states-and-behavior-as-types
My other comments right now will explain how the code can be modified to never require these three functions in the SwapCoin trait
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed these functions from SwapCoin
. Added a couple other functions to get the contract type, and whether contract information is known (other_privkey
for IncomingSwapCoin
, hash_preimage
for Incoming/OutgoingSwapCoin
), and the type string.
src/wallet_sync.rs
Outdated
for (multisig_redeemscript, swapcoin) in &self.incoming_swap_coins { | ||
Self::print_script_and_coin(multisig_redeemscript, swapcoin); | ||
} | ||
for (multisig_redeemscript, swapcoin) in &self.outgoing_swap_coins { | ||
Self::print_script_and_coin(multisig_redeemscript, swapcoin); | ||
} | ||
println!("swapcoin count = {}", self.swap_coins.len()); | ||
println!( | ||
"swapcoin count = {}", | ||
self.incoming_swap_coins.len() + self.outgoing_swap_coins.len() | ||
); | ||
} | ||
|
||
fn print_script_and_coin(script: &Script, coin: &dyn SwapCoin) { | ||
let contract_tx = coin.get_contract_tx(); | ||
println!( | ||
"{} {}:{} {}", | ||
Address::p2wsh(script, NETWORK), | ||
contract_tx.input[0].previous_output.txid, | ||
contract_tx.input[0].previous_output.vout, | ||
if coin.get_other_privkey().is_some() { | ||
" known" | ||
} else { | ||
"unknown" | ||
} | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can avoid using SwapCoin.get_other_privkey() here if we retain knowledge of the type (either IncomingSwapCoin or OutgoingSwapCoin). OutgoingSwapCoin will never have the field other_privkey
. Probably this function print_script_and_coin
should only take IncomingSwapCoins.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably this function print_script_and_coin should only take IncomingSwapCoins.
I think it's important to print all the coins in this context, and added an is_known
function to SwapCoin
. For IncomingSwapCoin
is tests the presence of hash_preimage
or other_privkey
, and for OutgoingSwapCoin
only tests for hash_preimage
.
src/main.rs
Outdated
compressed: true, | ||
key: bitcoin::secp256k1::PublicKey::from_secret_key( | ||
&secp, | ||
&swapcoin.contract_privkey, | ||
swapcoin.get_contract_privkey().unwrap(), | ||
), | ||
}; | ||
let type_string = if contract_pubkey | ||
== read_hashlock_pubkey_from_contract(&swapcoin.contract_redeemscript).unwrap() | ||
== read_hashlock_pubkey_from_contract(&swapcoin.get_contract_redeemscript()) | ||
.unwrap() | ||
{ | ||
"hashlock" | ||
} else { | ||
assert_eq!( | ||
contract_pubkey, | ||
read_timelock_pubkey_from_contract(&swapcoin.contract_redeemscript) | ||
read_timelock_pubkey_from_contract(&swapcoin.get_contract_redeemscript()) | ||
.unwrap() | ||
); | ||
"timelock" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As "timelock" and "hashlock" exactly match the OutgoingSwapCoin and IncomingSwapCoin types, we no longer need to do this whole part where we calculate the public key and compare it with the contract_redeemscript. Consequently we also don't need the function get_contract_privkey
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I replaced these tests with a function SwapCoin::contract_type
that directly returns the type string:
- IncomingSwapCoin => "hashlock"
- OutgoingSwapCoin => "timelock"
- WatchOnlySwapCoin => "watchonly"
I've done a first-pass review and written some comments. They're actually all related to one issue about not having three functions be in the SwapCoin trait. There's also another issue about how in |
I was wondering if there was only a need to check for I've added a fixup commit, and rebased on latest master. Let me know what you think. Will squash the fixup commit(s) once you're happy with the changes. |
a3f584f
to
06b00be
Compare
src/wallet_sync.rs
Outdated
@@ -604,20 +786,25 @@ impl Wallet { | |||
pub fn find_incomplete_coinswaps( | |||
&self, | |||
rpc: &Client, | |||
) -> Result<HashMap<[u8; 20], Vec<(ListUnspentResultEntry, &WalletSwapCoin)>>, Error> { | |||
) -> Result<HashMap<[u8; 20], Vec<(ListUnspentResultEntry, &dyn SwapCoin)>>, Error> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change this whole function a little bit to return HashMap::<[u8; 20]>, (Vec<(ListUnspentResultEntry, &IncomingSwapCoin)>, Vec<(ListUnspentResultEntry, &OutgoingSwapCoin)>)
. So make the IncomingSwapCoin and OutgoingSwapCoin be returned separately in different vectors.
Sorry about the delay on my end. Thanks for sticking with this. Just one requested change now, and after that please squish the commits. I'll have a bit of time right now if you reckon you'll be delayed I can just merge this PR and do the requested change myself. |
No worries, thanks for the review!
Rebased on latest master, and added the requested change. Let me know if you like it, or want me to revert. Makes the code a little more verbose, but has the advantage of concrete types in a couple places. If you like it, I'll squish the commits. |
I just tested if |
4b39730
to
2b7b188
Compare
Hopefully, the fix for the iterators in main, fix the reporting issue. If not, let me know, and I'll try to reproduce your test setup. Sidenote: should I work on setting up automated integration tests for situations like the one you mentioned? |
That last commit did not fix the issue. So I just put print statements everywhere myself and I tracked down the cause, which I wrote in a review comment here just now. Sidenote: Yes but not right now. I'm still working on code which will go alongside this PR which waits for the timeout branch of the contract transactions and then adds those coins to the wallet. |
Convert WalletSwapCoin into Incoming/OutgoingSwapCoin, and add a WalletSwapCoin trait for common functionality
Convert
WalletSwapCoin
intoIncoming/OutgoingSwapCoin
, and add aWalletSwapCoin
trait for common functionality