Closed dan-da closed 2 months ago
The name ChangeNotifyMethod
is a little confusing because:
OnChainPubKey
would be used for change. If it's going back to yourself, you don't need public key crypto and symmetric crypto suffices.Maybe just NotifyMethod
suffices? That's more of an invitation to elaborate than a suggestion.
yeah, I'm not yet really satisfied with UtxoNotifyMethod
and ChangeNotifyMethod
as they both have the same variants.
The reason they are distinct is that UtxoNotifyMethod
is used by the caller to actually provide PublicAnnouncement
to create_transaction()
. And that is done because create_transaction()
deals with Utxo and PublicAnnouncement, not GenerationAddress. That keeps create_transaction()
agnostic about the type of address used, which is good, I think. (and preserves prior behavior)
ChangeNotifyMethod
is used only for telling create_transaction() how to notify for the change output. In this case, create_transaction() generates the PublicAnnouncement itself, using a SpendingKey. So that kind of breaks the above model of being address-type agnostic... but then that code pre-exists this PR. This is only necessary because create_transaction() creates the change utxo if sum(inputs) > sum(outputs). Perhaps a cleaner/better solution would be to return an error in this case, which forces the caller to create the correct change utxo itself. With that modification, there is nothing special about the change utxo, it is an output created by the caller like any other. I am leaning toward this solution.
The name
ChangeNotifyMethod
is a little confusing because:
yeah, we can get rid of that enum entirely with above proposal.
- Non-change UTXOs can also have recipients that need to be notified. Is there a good reason to limit the struct's scope to exclude them?
Those utxo are taken care of by the UtxoNotifyMethod
enum. With above proposal, it would cover all utxo, including change.
- I don't foresee a world in which
OnChainPubKey
would be used for change. If it's going back to yourself, you don't need public key crypto and symmetric crypto suffices.
Fair point. Though it also applies to any output UTXO that can be claimed/spent by "my" wallet. So I think that create_transaction() should just throw an error in that case.
Does the above sound reasonable to you?
edit: I just reviewed the create_transaction() code again and found a complication. Presently the caller cannot construct a change utxo because they do not know the inputs and thus cannot calc total_spend which is needed to calc change.
Pursuing this approach further, the logical thing is to make the assemble_inputs_for_transaction()
method public, so then the caller can obtain the inputs, calc spend and change, and pass it all into create_transaction().
Taking the idea further, the caller can also create the ExpectedUtxo(s) and create_transaction() does not need to return them, which makes that API cleaner. It is more work for the caller, but I think the end result will be cleaner more sensible APIs, given the constraints.
anyway, that's the path I'm exploring now....
closing. obsoleted by #162.
Closes #122. Obsoletes #136
This PR builds on #136 which modifies GlobalState::create_transaction() to take
&self
instead of&mut self
and makes the state update (for expected_utxo) responsibility of the caller. The primary motivation is to avoid holding a write lock across the call to prove() which may take a very long time.This PR focuses on improving the flexibility and ergonomics of the create_transaction() API.
In particular, it improves on #136 in the following ways:
notify wallet of any incoming utxos
instead of the sub-case ofnotify wallet of incoming change utxo
-- as discussed with @aszepieniec.send_to_many()
which exposes multi-output functionality at the rpc level. Thesend()
endpoint now just wrapssend_to_many()
.send_to_many()
RPCsend_to_many()
to transmit to, which avoids an error case that was previously not logged and now triggered by the test case.UtxoNotifyMethod
andChangeNotifyMethod
enums for selectingOnChainPubKey
andOffChain
notifications: akaPublicAnnouncement
andExpectedUtxo
. It also has a variantOnChainSymetricKey
in preparation for when we add symmetric-key notifications as alternative to OffChain.UtxoReceiver
struct, which represents each output passed tocreate_transaction()
.These changes are a bit experimental. I think they are a net overall improvement to the API, but am open to criticisms/suggestions.
I should point out that the ability to select onchain/offchain notification per output utxo is available at the level of the rust API, ie
create_transaction()
, but is not available in the RPC API, which just uses the defaults. So this functionality is not presently exposed to end-users.One further change worth mentioning: this eliminates the pause/unpause miner steps inside send/send_to_many rpc calls. As I see it, a new block could arrive at any moment from a peer while we are creating/proving, so there is nothing special about mining in that regard. Maybe there's an argument to be made that we can have CPU contention and the Tx will take longer to prove(), however I don't think that is valid right now while mining is single-threaded. I am open to putting this back if it should prove necessary, but right now I don't see a need for the added complexity.
For purposes of reviewing, I would recommend to start with rpc_server.rs to see how usage has changed, then models/state/mod.rs and models/state/utxo_receiver.rs for most impl changes. Other files are mostly unit test adaptations.
ALSO: I noticed that our wallet is always just using derivation index 0. I wrote a couple wallet functions that pretend this is not the case, ie
is_wallet_utxo()
andget_known_spending_keys()
. This seems an area that needs attention, ie the wallet should keep track (state) of the last-used key index and increment each time a new wallet address is requested.