-
Notifications
You must be signed in to change notification settings - Fork 64
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
Implement listadresses #709
Conversation
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.
Approach ACK. Needs a bit more testing (and an entry in doc/API.md
) but it's in good shape!
08d7f7a
to
646c525
Compare
Let me know when this is ready for review by moving this out of draft / WIP. No rush! |
i think it is now ;) |
src/jsonrpc/api.rs
Outdated
@@ -258,6 +282,14 @@ pub fn handle_request(control: &DaemonControl, req: Request) -> Result<Response, | |||
} | |||
"getinfo" => serde_json::json!(&control.get_info()), | |||
"getnewaddress" => serde_json::json!(&control.get_new_address()), | |||
"listaddresses" => { | |||
let params = req.params.ok_or_else(|| { |
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 the parameters are optional, I'm wondering if you could keep params
as Option<Params>
and pass that to list_addresses
.
I'm able to run listaddresses
without any parameters so I guess req.params
is Some
also in that case and it works fine, but not sure if there might be a situation where it is None
.
@darosior may be able to help.
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.
you seems right, i wonder why Error::invalid_params
is not triggered when call listaddresses w/o args? shouldn't it in that case?
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.
That's most likely you tested with the CLI which always includes a params
entry in the JSONRPC request. But that's not mandated by the JSONRPC2 specs.
I agree with @jp1ac4 this shouldn't error if params is None. You can take inspiration from how list_coins
does this.
Could you rebase and squash your commits into a couple ones? I'll review then. |
3651896
to
fbad20d
Compare
I rebased and squash to 3 commits implement/test/fixes, feel free to tell me if you prefer I squash to a single one. |
Having tests in a separate commit is fine. However having fixups in a separate commit than the one where issues were introduced creates needless churn and confusion. That's fine for this time, but next time please squash the fixup commit(s) in the appropriate original commit(s). |
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.
Almost there, the main things are:
- There is an off by one when
count
is not provided - Let's not crash on insane inputs
- Let's not error if a
params
entry isn't given in the JSONRPC request, since all fields are optional
src/commands/mod.rs
Outdated
let child = bip32::ChildNumber::from_normal_idx(index) | ||
.expect("Failed to convert index to ChildNumber"); |
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.
Could we error instead of crashing if a value greater than 2**31 - 1
is passed for count? It's an insane argument to give to the command, but it's nicer to never crash on insane inputs.
Let's add an InvalidAddressCount
variant to the CommandError
enum and use it here and above?
src/jsonrpc/api.rs
Outdated
@@ -258,6 +282,14 @@ pub fn handle_request(control: &DaemonControl, req: Request) -> Result<Response, | |||
} | |||
"getinfo" => serde_json::json!(&control.get_info()), | |||
"getnewaddress" => serde_json::json!(&control.get_new_address()), | |||
"listaddresses" => { | |||
let params = req.params.ok_or_else(|| { |
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.
That's most likely you tested with the CLI which always includes a params
entry in the JSONRPC request. But that's not mandated by the JSONRPC2 specs.
I agree with @jp1ac4 this shouldn't error if params is None. You can take inspiration from how list_coins
does this.
fbad20d
to
3b84b33
Compare
comment have been adressed |
This comment wasn't addressed? #709 (comment) |
3b84b33
to
2660b77
Compare
right, it's done now |
@@ -37,6 +37,24 @@ def test_getaddress(lianad): | |||
assert res["address"] != lianad.rpc.getnewaddress()["address"] | |||
|
|||
|
|||
def test_listadresses(lianad): |
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.
nit:
def test_listadresses(lianad): | |
def test_listaddresses(lianad): |
Self::InvalidAddressCount => write!(f, "Invalid address count, should be under 2^31-1"), | ||
Self::InvalidAddressIndex => write!(f, "Invalid address index, should be under 2^31-1"), |
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.
Would be better to introduce a single enum variant, a general "invalid derivation index" which could be reused in the future.
if start_index > (2u32.pow(31) - 1) { | ||
return Err(CommandError::InvalidAddressIndex); | ||
} |
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.
(Here and below) Ok, this works. But it would be much clearer to use ChildNumber::from_normal_idx
's error or at the very least add a comment.
return Err(CommandError::InvalidAddressIndex); | ||
} | ||
|
||
let count = count.unwrap_or_else(|| receive_index.max(change_index) - start_index); |
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.
What if start_index
is larger than the maximum of the receive and change indexes? We need to really be careful about underflows in this code.
if count == 0 { | ||
let out: Vec<AddressInfo> = Vec::new(); | ||
return Ok(ListAddressesResult::new(out)); | ||
} |
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.
It's a bit ugly to special case 0 here to avoid the checked_sub
below to return None
. Could get rid of the necessity for a checked_sub altogether by using an exclusive range ((x..y)
) below instead of an inclusive one ((x..=y)
).
@@ -860,6 +927,24 @@ impl GetAddressResult { | |||
} | |||
} | |||
|
|||
#[derive(Debug, Clone, Serialize)] |
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.
Would be nice to make it PartialEq, Eq too.
#[test] | ||
fn listaddresses() { |
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.
Would be good to check bounds here for hardened derivation index, overflows and underflows.
.as_ref() | ||
.and_then(|p| p.get(0, "start_index")) | ||
.and_then(|i| i.as_u64()) | ||
.and_then(|i| i.try_into().ok()); |
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 shouldn't silently ignore invalid parameters to listaddresses
.
I've addressed my comments here: https://github.com/darosior/liana/tree/get_all_addresses. Apparently i can't push them to your PR, so i'll open a follow-up.. |
See #808. |
0812a12 jsonrpc: don't ignore invalid params to listaddresses (Antoine Poinsot) d533820 commands: listaddresses cleanups (Antoine Poinsot) Pull request description: This addresses my latest review from #709. ACKs for top commit: jp1ac4: ACK 0812a12 Tree-SHA512: 6f708fd2f1aa2f229a5c78a35e363870ef390513cce10fc6a5938b49e6b7ee5be9205bc4566376750e4f7eeea404709ce6d8c7a29df15b9216b8dbcf4b4fed7e
address #681
todo:
edit: i'm really new to rust, don't hesitate to kick my ass when i write stupid code