-
Notifications
You must be signed in to change notification settings - Fork 65
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
adding the commands for proof-of-reserves using the separate repository #48
adding the commands for proof-of-reserves using the separate repository #48
Conversation
Rather than a merge commit (4fca4b8) it'd be better to rebased this branch on the latest |
Will the |
4fca4b8
to
c16595f
Compare
So far I tested it only with electrum. I assume it could be made to work with others as well, but I didn't look into that so far. |
d7063cc
to
2ee0d40
Compare
I just updated the implementation to better separate between internal and external proof validation. The internal validation with a wallet (that can be built with a public key descriptor) can be used with any blockchain connector. It is only the external validation with addresses that is only available with electrum. The latter one is the more important one for me, and I'm ok with it only being available with electrum for now. |
9e26917
to
3d192ec
Compare
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.
untested Concept ACK. 3d192ec
Thanks for working on this, it can be a really useful feature. And I like the current external trait impl on bdk::wallet, that makes the reserves crate really portable without putting it into bdk crate directly. But this could be eventually added to the BDK project as a util library.
I will try to test the whole thing in more detail. I am wondering what is stopping us from using other blockchains like core RPC. From your test script it seems its working fine with compact filters. Will look and report back.
Below are few minor nits in mean time.
Yes, the plan for bdk-reserves was from the beginning to add it to the BDK project as a util library. |
3d192ec
to
3cc81db
Compare
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.
initial tACK 3cc81db. I haven't run the test scripts, syncing my testnet node now. But there should not be an issue. Will play some more with it and report back if I find something odd.
Below are few more comments.
d8a6064
to
4a91e63
Compare
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.
reACK 4a91e63
Just few more small nits and I think its good to go.
Also I think the doc comments here
Lines 192 to 242 in f8f65f2
/// let expected_cli_opts = CliOpts { | |
/// network: Network::Testnet, | |
/// subcommand: CliSubCommand::Wallet { | |
/// wallet_opts: WalletOpts { | |
/// wallet: "main".to_string(), | |
/// verbose: false, | |
/// descriptor: "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/44'/1'/0'/0/*)".to_string(), | |
/// change_descriptor: None, | |
/// #[cfg(feature = "electrum")] | |
/// electrum_opts: ElectrumOpts { | |
/// timeout: None, | |
/// server: "ssl://electrum.blockstream.info:60002".to_string(), | |
/// stop_gap: 10 | |
/// }, | |
/// #[cfg(feature = "esplora-ureq")] | |
/// esplora_opts: EsploraOpts { | |
/// server: "https://blockstream.info/testnet/api/".to_string(), | |
/// read_timeout: 5, | |
/// write_timeout: 5, | |
/// stop_gap: 10 | |
/// }, | |
/// #[cfg(feature = "esplora-reqwest")] | |
/// esplora_opts: EsploraOpts { | |
/// server: "https://blockstream.info/testnet/api/".to_string(), | |
/// conc: 4, | |
/// stop_gap: 10 | |
/// }, | |
/// #[cfg(feature = "rpc")] | |
/// rpc_opts: RpcOpts{ | |
/// address: "127.0.0.1:18443".to_string(), | |
/// auth: ("user".to_string(), "password".to_string()), | |
/// skip_blocks: None, | |
/// }, | |
/// #[cfg(feature = "compact_filters")] | |
/// compactfilter_opts: CompactFilterOpts{ | |
/// address: vec!["127.0.0.1:18444".to_string()], | |
/// conn_count: 4, | |
/// skip_blocks: 0, | |
/// }, | |
/// #[cfg(any(feature="compact_filters", feature="electrum", feature="esplora"))] | |
/// proxy_opts: ProxyOpts{ | |
/// proxy: None, | |
/// proxy_auth: None, | |
/// retries: 5, | |
/// }, | |
/// }, | |
/// subcommand: WalletSubCommand::OnlineWalletSubCommand(Sync { | |
/// max_addresses: Some(50) | |
/// }), | |
/// }, | |
/// }; |
Lines 362 to 403 in f8f65f2
/// let expected_wallet_opts = WalletOpts { | |
/// wallet: "main".to_string(), | |
/// verbose: false, | |
/// descriptor: "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/44'/1'/0'/0/*)".to_string(), | |
/// change_descriptor: None, | |
/// #[cfg(feature = "electrum")] | |
/// electrum_opts: ElectrumOpts { | |
/// timeout: None, | |
/// server: "ssl://electrum.blockstream.info:60002".to_string(), | |
/// stop_gap: 10 | |
/// }, | |
/// #[cfg(feature = "esplora-ureq")] | |
/// esplora_opts: EsploraOpts { | |
/// server: "https://blockstream.info/testnet/api/".to_string(), | |
/// read_timeout: 5, | |
/// write_timeout: 5, | |
/// stop_gap: 10 | |
/// }, | |
/// #[cfg(feature = "esplora-reqwest")] | |
/// esplora_opts: EsploraOpts { | |
/// server: "https://blockstream.info/testnet/api/".to_string(), | |
/// conc: 4, | |
/// stop_gap: 10 | |
/// }, | |
/// #[cfg(feature = "compact_filters")] | |
/// compactfilter_opts: CompactFilterOpts{ | |
/// address: vec!["127.0.0.1:18444".to_string()], | |
/// conn_count: 4, | |
/// skip_blocks: 0, | |
/// }, | |
/// #[cfg(feature = "rpc")] | |
/// rpc_opts: RpcOpts{ | |
/// address: "127.0.0.1:18443".to_string(), | |
/// auth: ("user".to_string(), "password".to_string()), | |
/// skip_blocks: None, | |
/// }, | |
/// #[cfg(any(feature="compact_filters", feature="electrum", feature="esplora"))] | |
/// proxy_opts: ProxyOpts{ | |
/// proxy: None, | |
/// proxy_auth: None, | |
/// retries: 5, | |
/// }, |
I don't see how the new sub commands would fit in these examples. They only list the wallet options. But reserves didn't add anything there. It only adds sub-commands. |
68722e2
to
4556d8e
Compare
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.
tACK 4556d8e
I don't see how the new sub commands would fit in these examples. They only list the wallet options. But reserves didn't add anything there. It only adds sub-commands.
Ah right, my bad.. This has nothing to do with wallet opts..
I think ultimately we can document this on the website docs in a chapter on |
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.
Tested and looks good. I have a few small requests to make the cli more consistent.
Also I noticed that my proof of reserves validated even though one of the UTXOs wasn't confirmed on the (testnet) blockchain yet. Is this a known issue?
src/lib.rs
Outdated
ProduceProof { | ||
/// Sets the message | ||
#[structopt(name = "MESSAGE", long = "message")] | ||
msg: Option<String>, |
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.
From code looks like this is not an optional parameter so should be:
msg: Option<String>, | |
msg: String, |
src/lib.rs
Outdated
VerifyProof { | ||
/// Sets the PSBT to verify | ||
#[structopt(name = "BASE64_PSBT", long = "psbt")] | ||
psbt: Option<String>, |
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.
Same as above not optional:
psbt: Option<String>, | |
psbt: String, |
src/lib.rs
Outdated
psbt: Option<String>, | ||
/// Sets the message to verify | ||
#[structopt(name = "MESSAGE", long = "message")] | ||
msg: Option<String>, |
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.
Same as above not optional:
msg: Option<String>, | |
msg: String, |
src/lib.rs
Outdated
@@ -1076,6 +1134,47 @@ where | |||
let txid = maybe_await!(wallet.broadcast(tx))?; | |||
Ok(json!({ "txid": txid })) | |||
} | |||
#[cfg(feature = "reserves")] | |||
ProduceProof { msg } => { | |||
let message = if let Some(msg) = msg { |
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.
If msg
is not optional and is enforced by StructOpt then this logic isn't needed.
src/lib.rs
Outdated
} | ||
#[cfg(feature = "reserves")] | ||
VerifyProof { psbt, msg } => { | ||
let psbt = if let Some(psbt) = psbt { |
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.
If psbt
is not optional and is enforced by StructOpt then this logic can be simplified.
src/lib.rs
Outdated
} else { | ||
panic!("Missing `psbt` option") | ||
}; | ||
let message = if let Some(msg) = msg { |
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.
If msg
is not optional and is enforced by StructOpt then this logic isn't needed.
You also will need to rebase on master to pickup CI testing against our new stable rust version (1.56.1). |
No, I was not aware of this. |
4d67e95
to
fb9ae70
Compare
src/lib.rs
Outdated
let _max_confirmation_height = current_height - confirmations.unwrap_or(6); | ||
|
||
// ToDO: use this line after upgrading to 0.14 | ||
//let spendable = maybe_await!(wallet.verify_proof(&psbt, &msg, max_confirmation_height))?; |
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.
after #60 is merged to master.
109a44d
to
09a9435
Compare
src/lib.rs
Outdated
#[structopt(name = "MESSAGE", long = "message")] | ||
msg: String, | ||
/// Sets the number of block confirmations for UTXOs to be considered. If nothing is specified, 6 is used. | ||
#[structopt(name = "CONFIRMATIONS", long = "confirmations")] |
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 think a better way to specify the default for the cli is like this, it will also show in the help so you don't need to mention it in the above docs line:
#[structopt(name = "CONFIRMATIONS", long = "confirmations")] | |
#[structopt(name = "CONFIRMATIONS", long = "confirmations", default_value = "6")] |
src/lib.rs
Outdated
msg: String, | ||
/// Sets the number of block confirmations for UTXOs to be considered. If nothing is specified, 6 is used. | ||
#[structopt(name = "CONFIRMATIONS", long = "confirmations")] | ||
confirmations: Option<u32>, |
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.
If you specify the default_value
via struct opt then you don't need an Option here:
confirmations: Option<u32>, | |
confirmations: u32, |
src/lib.rs
Outdated
let psbt = base64::decode(&psbt).unwrap(); | ||
let psbt: PartiallySignedTransaction = deserialize(&psbt).unwrap(); | ||
let current_height = wallet.client().get_height()?; | ||
let _max_confirmation_height = current_height - confirmations.unwrap_or(6); |
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.
If default is specified via struct opt then this can be simplified a little and by moving to struct opt will always be in sync with cli docs:
let _max_confirmation_height = current_height - confirmations.unwrap_or(6); | |
let _max_confirmation_height = current_height - confirmations; |
d6a9564
to
75dde25
Compare
After adding the checks for block_height, many manual tests of the internal verify_proof() failed. |
75dde25
to
6f07303
Compare
d8ae6e6
to
1567bc1
Compare
1567bc1
to
7e6a4c8
Compare
ACK 7e6a4c8 I would like to eventually change the integration tests to use |
Thanks for reviewing, testing and all the proposals for improvements @notmandatory and @rajarshimaitra |
@ulrichard Thanks for working on this. I will test the latest commits and merge it soon. @notmandatory IIUC for regtest support we need this to work with RPC backend right? |
We can use the |
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.
ReACK 7e6a4c8
@notmandatory yes that makes sense. Previously we didn't need such integrations tests here, but now that we need one, maybe it would make sense to also add some generic wallet tests with regtest rpc too along with PoR tests? We should be able to do all the stuffs in PoR except the ExternalReserves
thing with RPC. I will open a new issue to keep track of it.
@ulrichard I am merging this now. Below is one future improvement question.
dependencies = [ | ||
"base64 0.11.0", | ||
"bdk", | ||
"bitcoinconsensus", |
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.
bdk
has a verify
feature that uses bitcoinconsensus
. Would there a be a way in future to use bdk::verify
instead of bitcoinconsensus
in the bdk-reserves
dependency?
adding the commands for proof-of-reserves using the separate repository
Notes to the reviewers
Checklists
All Submissions:
cargo fmt
andcargo clippy
before committingNew Features:
CHANGELOG.md
Bugfixes: