Coder Social home page Coder Social logo

grin-wallet's Introduction

Continuous Integration Coverage Status Chat Support Release Version License

Grin Wallet

This is the reference implementation of Grin's wallet. It consists of 2 major pieces:

  • The Grin Wallet APIs, which are intended for use by Grin community wallet developers. The wallet APIs can be directly linked into other projects or invoked via a JSON-RPC interface.

  • A reference command-line wallet, which provides a baseline wallet for Grin and demonstrates how the wallet APIs should be called.

Usage

To use the command-line wallet, we recommend using the latest release from the Releases page. There are distributions for Linux, MacOS and Windows.

Full documentation outlining how to use the command line wallet can be found on Grin's Wiki

License

Apache License v2.0

grin-wallet's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

grin-wallet's Issues

Add --password-file option to the grin wallet command

The problem is if you want to start off wallet listen and owner_apis you have to input your wallet password or use the flag -p.
The problem with -p is that your password will be there in plaintext within bash history or ps ux.

A solution would be to support file passwords.
That way the service can be started and the file with the password deleted after the successful start.

Monero has this option and it works very well there.

Define transaction states

Creating an issue to track. Relevant chat in gitter/design.

  • What are the different states a transaction/slate can have?
  • What are the valid transitions between these states?

Current proposal

  1. Created: Slate was generated.
  2. Pending: Slate has been passed to the other party(ies), and you are awaiting a response.
  3. Returned: Slate was processed and returned to whoever you got it from, and you are now awaiting to see the transaction.
  4. Finalized: A valid tx was broadcasted to the blockchain.
  5. Unconfirmed: A tx is on the chain but not yet received enough confirmations.
  6. Confirmed: A tx was confirmed on the chain.
  7. Cancelled: Tx was manually canceled by a user.
  8. Expired: A transaction expired before being finalized. (For example if other party cancelled.)

Open problems / critique

  • Some of these states as they are described above are implicit, there's no certainty that they have transitioned. Returned for example is an assumption the wallet has to make in the case of file-based tx building. Similarly, currently a transacting party will not know whether the other party Cancelled, therefore the transaction can only be Expired on their end. This is not ideal.

  • @sesam writes: I'm also not fully sure, but I think 4. finalized now no longer means sent to chain, and we'd need a local wallet state 4.1. sent (stemmed), 4.2 sent (fluffed). Then 5. unconfirmed (publicly seen/in the wild). Under 6. confirmed we could also have a parenthesis (1 confirmation) up to 10 confirmations, then Confirmed (trusted final)

LmdbErr(Error::Code(11, 'Resource temporarily unavailable'))

I see the following failure in "grin wallet send" intermittently (ya, I know, sorry).
I can get more logs to confirm, but it looks a bit like a coinbase is being built at the same time, so maybe that process legitimately has the db locked? Should the second process wait and/or retry a little bit before failing? A default 5 second wait would probably help a lot.

20181129 00:56:12.490 DEBUG grin_wallet::libwallet::internal::updater - receive_coinbase: BlockFees { fees: 0, height: 59860, key_id: Some(Identifier(0300000000000000000000018e00000000)) }
20181129 00:56:57.477 DEBUG grin_wallet::types - Using wallet seed file at: /wallet/wallet_data/wallet.seed
20181129 00:56:57.518 DEBUG grin_wallet::libwallet::internal::updater - receive_coinbase: built candidate output - Identifier(0300000000000000000000018e00000000), 0300000000000000000000018e00000000
20181129 00:56:57.519 DEBUG grin_wallet::libwallet::internal::updater - receive_coinbase: BlockFees { fees: 0, height: 59861, key_id: Some(Identifier(0300000000000000000000018e00000000)) } 
20181129 00:57:37.658 DEBUG grin_wallet::types - Using wallet seed file at: /wallet/wallet_data/wallet.seed 
20181129 00:57:37.683 DEBUG grin_wallet::libwallet::internal::updater - receive_coinbase: built candidate output - Identifier(0300000000000000000000018e00000000), 0300000000000000000000018e00000000 
20181129 00:57:37.683 DEBUG grin_wallet::libwallet::internal::updater - receive_coinbase: BlockFees { fees: 8000000, height: 59862, key_id: Some(Identifier(0300000000000000000000018e00000000)) } 
20181129 01:00:16.923 INFO grin_util::logger - log4rs is initialized, file level: Debug, stdout level: Debug, min. level: Debug 
20181129 01:00:16.923 INFO grin - Using wallet configuration file at /wallet/grin-wallet.toml 
20181129 01:00:16.923 INFO grin - This is Grin version 0.4.1 (git 0.4.0-134-g1ea82d9), built for x86_64-unknown-linux-gnu by rustc 1.30.1 (1433507eb 2018-11-07). 
20181129 01:00:16.923 DEBUG grin - Built with profile "release", features "". 
20181129 01:00:16.924 DEBUG grin_wallet::types - Using wallet seed file at: /wallet/wallet_data/wallet.seed 
20181129 01:00:16.953 ERROR grin_util::logger -  
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: LmdbErr(Error::Code(11, 'Resource temporarily unavailable'))': libcore/result.rs:1009stack backtrace: 
   0:     0x556d81dc962c - backtrace::backtrace::trace::h342407aacfccaa6d 
   1:     0x556d81dc88a2 - <backtrace::capture::Backtrace as core::default::Default>::default::h37593dc9d5a9f86d 
   2:     0x556d81dc8918 - backtrace::capture::Backtrace::new::ha2a3d34ce8fdbf26 
   3:     0x556d81d564df - grin_util::logger::send_panic_to_log::{{closure}}::hf1fe78813a52192f 
   4:     0x556d81edafe3 - std::panicking::rust_panic_with_hook::h86e619a638415243 
                        at libstd/panicking.rs:481 
   5:     0x556d81edab49 - std::panicking::continue_panic_fmt::h2d2d2bfb065a70b2 
                        at libstd/panicking.rs:391 
   6:     0x556d81edaa45 - rust_begin_unwind 
                        at libstd/panicking.rs:326 
   7:     0x556d81f36d4b - core::panicking::panic_fmt::h2155aa66b67fe83c 
                        at libcore/panicking.rs:77 
   8:     0x556d818fecf8 - core::result::unwrap_failed::h4cb13a052906581a 
   9:     0x556d819122ed - <grin_wallet::lmdb_wallet::LMDBBackend<C, K> as grin_wallet::libwallet::types::WalletBackend<C, K>>::set_parent_key_id_by_name::hcb71e44e8810b200 
  10:     0x556d818f6fac - grin_wallet::instantiate_wallet::h48829e0d8d23a017 
  11:     0x556d81760245 - grin::real_main::h400924db3933ad72 
  12:     0x556d8175a5d5 - grin::main::h528ac062e526aa0c 
  13:     0x556d816dd952 - std::rt::lang_start::{{closure}}::ha951655b798225dc 
  14:     0x556d81eda9e2 - std::rt::lang_start_internal::{{closure}}::hf358dd5cfeb0e6cb 
                        at libstd/rt.rs:59 
                         - std::panicking::try::do_call::h47665672c57b11e4 
                        at libstd/panicking.rs:310 
  15:     0x556d81efff89 - __rust_maybe_catch_panic 
                        at libpanic_unwind/lib.rs:103 
  16:     0x556d81ee5d15 - std::panicking::try::h8475f4f88883fab0 
                        at libstd/panicking.rs:289 
                         - std::panic::catch_unwind::hf17f60e34fd385b1 
                        at libstd/panic.rs:392 
                         - std::rt::lang_start_internal::had9505969b8e20a2 
                        at libstd/rt.rs:58 
  17:     0x556d817622a3 - main 
  18:     0x7f2e9a34a2e0 - __libc_start_main 
  19:     0x556d816a4a69 - _start 
  20:                0x0 - <unknown> 
 
 
20181129 01:00:37.058 DEBUG grin_wallet::types - Using wallet seed file at: /wallet/wallet_data/wallet.seed 
20181129 01:00:37.096 DEBUG grin_wallet::libwallet::internal::updater - receive_coinbase: built candidate output - Identifier(0300000000000000000000018e00000000), 0300000000000000000000018e00000000 
20181129 01:00:37.097 DEBUG grin_wallet::libwallet::internal::updater - receive_coinbase: BlockFees { fees: 8000000, height: 59862, key_id: Some(Identifier(0300000000000000000000018e00000000)) } 
20181129 01:00:48.587 DEBUG grin_wallet::types - Using wallet seed file at: /wallet/wallet_data/wallet.seed 
20181129 01:00:48.658 DEBUG grin_wallet::libwallet::internal::updater - receive_coinbase: built candidate output - Identifier(0300000000000000000000018e00000000), 0300000000000000000000018e00000000 
20181129 01:00:48.658 DEBUG grin_wallet::libwallet::internal::updater - receive_coinbase: BlockFees { fees: 0, height: 59863, key_id: Some(Identifier(0300000000000000000000018e00000000)) } 
20181129 01:00:57.195 DEBUG grin_wallet::types - Using wallet seed file at: /wallet/wallet_data/wallet.seed 
20181129 01:00:57.232 DEBUG grin_wallet::libwallet::internal::updater - receive_coinbase: built candidate output - Identifier(0300000000000000000000018e00000000), 0300000000000000000000018e00000000 
20181129 01:00:57.232 DEBUG grin_wallet::libwallet::internal::updater - receive_coinbase: BlockFees { fees: 0, height: 59864, key_id: Some(Identifier(0300000000000000000000018e00000000)) } 
20181129 01:03:57.035 DEBUG grin_wallet::types - Using wallet seed file at: /wallet/wallet_data/wallet.seed 
20181129 01:03:57.091 DEBUG grin_wallet::libwallet::internal::updater - receive_coinbase: built candidate output - Identifier(0300000000000000000000018e00000000), 0300000000000000000000018e00000000 
20181129 01:03:57.091 DEBUG grin_wallet::libwallet::internal::updater - receive_coinbase: BlockFees { fees: 14000000, height: 59864, key_id: Some(Identifier(0300000000000000000000018e00000000)) }
-- VISUAL --                                                                                                            59        15217,196     99%

rewind_bullet_proof fails on multi-party / multi-sig commitment

See here: mimblewimble/rust-secp256k1-zkp#31 (comment)
And here: mimblewimble/rust-secp256k1-zkp#37

Would be required in order to restore a multi-signature output.
Currently there's no solution identified.

Relevant gitter chat

jaspervdm @jaspervdm 07:45
@garyyu yes it fails, I expected that. I haven’t tried to fix it. Normally it is used for wallet restore but I haven’t thought of a way to restore a multi signature output, which is why I didnt pay much attention to the rewind

Gary Yu @garyyu 07:47
@jaspervdm Is it a complex topic? can be completed this time or leave it later?

jaspervdm @jaspervdm 07:52
I can try to make it work using the common nonce, but a wallet restore won’t restore the output

Gary Yu @garyyu 07:52
wallet restore is an important feature, since people often face some problems and need restore.

jaspervdm @jaspervdm 07:54
I don’t think it’s possible, at least I’m not smart enough to think of a way. You would have to use all the private nonces to make it work for all parties, but you can’t hide that much information
If you know of a way, let me know and I can add it

Gary Yu @garyyu 07:55
@jaspervdm
but a wallet restore won’t restore the output
because for multi-party commitment x1*G+x2*G+v*H, party A only know x1, that’s why restore doesn’t work. right?

jaspervdm @jaspervdm 07:56
Essentially yes
You need external information
It’s a bit unfortunate

Gary Yu @garyyu 07:58
So, we need keep x2*G just as safe as wallet.seed, then we can restore the multi-party output.
So, it’s feasible, if you can make the rewind_bullet_proof works on common nonce. :smile:

jaspervdm @jaspervdm 08:00
Yes but you need to store the common nonce, but at that point you might as well store the whole output, making rewinding unnecessary
To spend the output you need to save even more information, namely how to contact the other parties
That will never be recovered by a restore

Gary Yu @garyyu 08:04
@jaspervdm oh, that make sense. If need keep both x2*G and common nonce, people can choose directly store the output.

jaspervdm @jaspervdm 08:04
Yeah

Gary Yu @garyyu 08:05
Yes agree! it seems that the multi-party commitment is a huge topic, not so simple.
@jaspervdm Okay then. So, I will clean up that PR and leave some comments for rewind, and close it 

slate serialization compatibility to 1.0.x

wallet send to 1.0.x wallet fail, and the error log on 1.0.x wallet:

Generic error: Invalid request body: invalid type: string "e1c141a8fce73ca7e8c546a865ba26ae1879259ab366fc54fd502bf0c04dc5fa", expected an array of length 32 at line 1 column 147 }

Looks like we didn't successfully compatible with 1.0.x slate serialization, but I remember we did.
To be checked...

Unconfirmed (txpool) vs. really unconfirmed (stempool) when receiving a tx

Running a wallet receiver I see a variety of outputs in "unconfirmed" state -

  • If I receive a "stem" tx my output is unconfirmed (and I don't necessarily know when its going to confirm)
  • If I receive a "fluff" tx then the output is also unconformed (but I can reasonably expect it confirm on the next block)

We can actually differentiate between these two different states via the wallet + node, based on the tx being in the actual tx pool or just in the stempool.

It would be useful to visually differentiate between these when running -

  • grin wallet info
  • grin wallet outputs
  • etc.

Improve issue_send_tx api make dest parameter optional

When using the post-issue-send-tx from owner_api.
I have to add both parameters

"method": "file",
"dest": "/tmp/grin.tx",

Even if I am only interested in the response.

It would be perfect if there could be another method called api or response where the dest is not needed.
It would also work if both methodand dest where optional.

This should be very easy to improve.

[META] API V2 Tasks

Meta issue for work to support the new V2 API

  • Add doctests for every OwnerAPI method, OwnerAPI doctests will serve as jsonrpc documentation. See OwnerAPI::accounts for an example.
  • Add links to docs for APIOwner methods from each OwnerAPI method doc
  • Implement fn initiate_tx(..) -> Result<(Slate, OutputLockFn<W, C, K>), Error> without using a callback
  • Implement fn tx_lock_outputs(.. , mut lock_fn: OutputLockFn<W, C, K>) -> Result<(), Error> without using a callback
  • Implement issue_send_tx like in refwallet/src/controller.rs Edit: Would rather have consumers of the API calling all methods exactly as they are in the api, which now works with a bit more granularity than the legacy issue_send_tx (which does a bit too much)
  • Either A) Depreciate APIOwner in favor of OwnerAPI, or B) Rename OwnerAPI to be more decriptive e.g. RPCAPIOwner
  • Add ForeignAPI trait
  • Add jsonrpc_client macro for typed client generation
  • Possibly automatically generate clients in other languages such as javascript
  • Changes and refinements to the API itself (ongoing)

Add health check to foreign wallet API

The foreign wallet API seems only to have two POST apis. I want to host my foreign wallet API behind an AWS load balancer so that it can do the SSL termination for me. However, it requires some simple GET request to check whether the listener is up. It would be nice to have some simple status call in addition to the two POST commands.

Wallet API V2 - Suggestions

The current HTTP/json wallet API wasn't really designed in any way, it grew over time and currently doesn't do the best job at things it should be doing, such as exposing function parameters and returning relevant error messages. While a lot of changes to the 'real' underlying APIs have occurred recently, I haven't made any changes to the json API wrapper to allow existing applications continue to work as before.

I'm considering what to do for a version 2, and I think however it's built it should simply be a json wrapper around the 'real' Owner and Foreign APIs, which you'd get directly if you linked code against grin_wallet, are defined here (starting to document them properly): https://github.com/mimblewimble/grin/blob/master/wallet/src/libwallet/api.rs

Doing it this way has a few advantages, in that the same documentation can be used (the JSON API documentation can just point to the rustdoc generated API and will be more consistency regardless of how apps are linked.

I'm currently leaning towards using JSON RPC instead of the current RESTy-type API that's there are the moment. The wallet doesn't operate in a very CRUDdy fashion, and I think JSON RPC suits the workflow much better, is easier to manage and is much more suitable for handling and returning appropriate errors. I'd really like this layer to be a thin wrapper, would love it even more if there were a way to automatically generate it and ensure the documentation is generated directly from the code.

So as not to break existing compatibility for launch, I'd probably prefer to leave the existing API in place for now, and have the new version of the API on another endpoint. We'd then retire the older API at a later date.

These are my current thoughts on what should happen here, throwing this open as I'm quite happy to take suggestions or pointers as to what the V2 wallet HTTP/JSON API should look like.

Current Wallet API Doesn't Allow Merchants to Differentiate Payers

If a merchant were to programmatically implement an application that takes Grin deposits, as of right now there is no variable that can be parsed in the wallet owner API that would allow the merchant to differentiate a deposit of one payer from another payer's if they deposit the same amount at roughly the same time.

Monero had initially solved this problem with payment IDs that a merchant would provide to the payer before a transaction for them to specify during the transaction in a separate field. This turned out to be a terrible solution that not only compromised privacy at the network level but also created a UX nightmare, where exchanges would ask people to attach a certain payment ID to their transaction, the payers then not doing it due to inexperience or negligence, and the merchants having to sift through the transactions manually to find the payment, resulting in enormous productivity losses all around, users losing their funds due to merchants being unwilling to go through the hassle and a terrible experience for all involved, creating a perception for newcomers that this currency is hard to use and easy to lose.

After Monero had implemented integrated addresses, where the payment ID was baked into the address that the merchants provided to their users for deposits this UX issue was solved at the protocol level, but for years merchants kept using old-style payment IDs, opting to charge their users for finding missing transactions rather than implement the new integrated addresses. Due to backwards compatibility, this problem is still plaguing Monero even to this day.

This is why, in the case of Grin, telling the payer to add a message to the transaction with their merchant portal username is a terrible solution, in my opinion.

The ideal solution, in my view, would be a field (let's call it payer-id) that could be specified or saved by the receiver during their stage of the transaction creation, and that the receiver can later parse from a field in the retrieve_txs method of the owner wallet API when the transaction gets added to the blockchain (note, this does not necessarily have to be something that is stored on the blockchain, it could be a transaction-specific property that can be associated to a payer-id at the wallet level). This way a merchant would be able to link together all the deposits received from a given user due to that user being provided the same payer-id by the merchant's platform, just like when a payer is given the same integrated address to deposit to in Monero, allowing the merchant to easily scan all transactions from a given payer.

I don't know whether this kind of solution is possible for a MW blockchain, so, in case it isn't, I just want to emphasize that the main requirements for this solution are as follows:

  1. It has to require ZERO extra actions from the payer, all the differentiation logic should be done by the merchant.
  2. It has to either be something the merchant can specify OR something that a merchant can save before or during a transaction creation that is unique to this transaction or payer, that will be later
  3. something that the merchant can retrieve during the scanning of an incoming transaction from the blockchain. I.e. a field in the retrieve_txs method of the owner wallet API.

I also believe this should be prioritized to be implemented before the mainnet launch so as to allow merchants to prepare for launch and, more crucially, avoid transaction uniformity issues in the future (e.g. in Monero the transactions that have a payment ID can have a fingerprint different from the ones that don't).

Can't recover wallet if .grin/wallet_data/ folder don't exists already

Can't recover from phase if I firstly not init the wallet, then I can recover my existing wallet from phrase.
Recover command can't create wallet_data folder.

If I create wallet_data folder manually then recover works, creates wallet.seed file there.

20190307 21:58:36.353 ERROR grin_refwallet::command - Error recovering seed - IO error
Wallet command failed: IO error

Feature request: Offline send

I'd like to be able to send transactions from a machine without network access, however this doesn't seem to be currently supported. Correct me if I'm wrong, but the finalize command expects to be able to broadcast the finalized transaction immediately, so if the sending wallet is offline, it won't be able to complete the send, receive, finalize sequence.

I think this is valuable for security, since it allows sending funds from secure machine that isn't connected to the internet.

The simplest implementation would be to add an option to finalize to dump the final transaction, which could then be moved to an online machine for broadcast. Or, if #2473 allowed an online-invoice, offline-send, online-finalize flow, that would work too, and would potentially mean one less transfer between machines. (As opposed to an offline-send, online-receive, offline-finalize-dump, online-broadcast flow.)

can not get refreshed balance with /v1/wallet/owner/retrieve_summary_info?refresh

Describe the bug
By /v1/wallet/owner/retrieve_summary_info?refresh I can get wallet grin balance, but this balance is not refreshed, it is not latest
After run 'grin wallet check" and then run /v1/wallet/owner/retrieve_summary_info?refresh, then will get correct balance

Please tell me how to get the refreshed and latest grin balance by API

Transaction state doesn't match between sender and recipient

I've previously opened issue #2318 but this has happened again. I'm running version 1.0.0 and the sender has transaction marked as confirmed=false, while recipient has confirmed=true. When I run check nothing changes. How to proceed with this?

[META] Wallet Roadmap

Just a few thoughts on where I think core wallet development should be heading over the next while, roughly in order of when I think they should happen. Obviously all open for discussion, but I'd like to keep everyone working on the wallet on roughly the same page:

  • Misc additions to the Owner and Foreign APIs, such as 'invoicing' (payee initiated transactions,) and other enhancements that can be added over time.
  • v2 API Started here: #2 but will shortly become a meta-issue with several chunks of work that need doing. The main idea with the v2 API is to ensure JSONRPC stubs and documentation can be generated directly from the core rust APIs, to minimize the overhead in maintaining them and ensuring changes will be picked up as automatically as possible. Also this work should result in fewer bugs in the future due to differing code paths to call the same APIS. For instance. For instance the command line client currently links the rust structs directly while the current http client has manually-written stubs exposed that behave slightly differently from the command line. It's hoped that all consumers of the v2 interface will use the exact same interface, the only difference being the version of the generated stubs that are called.
  • API clients Following from above, it should be possible to automatically generate clients that call the v2 JSON RPC api, (javascript being an obvious target).
  • Integration Test suite with the v2 API in place, we need a comprehensive test suite calling JSONRPC directly and exactly how real clients would be doing it. There is already a start of a testing framework in place that simulates wallet to chain and wallet-to-wallet communication in-process, without having to open ports are the like. This needs to be extended a bit and tests written directly against the V2 API.
  • Persistent process command-line wallet or whatever you want to call this. At the moment the command line wallet lives for as long as it takes to execute a command. It should really behave more like wallet713 by default, whereby you start a wallet session and enter commands in its own command line. This version of the command line client should also use the v2 API via JSONRPC instead of linking directly, again to minimize the number of different code paths accessing the API.

Live Wallet Backup

Is your feature request related to a problem? Please describe.
It is disruptive and difficult to stop all grin wallet services to make a backup copy. It means downtime for an always-on service.

Describe the solution you'd like
I would like to be able to back up the wallet data while the wallet services are running.

Describe alternatives you've considered
Scheduled down time

Additional context
None.

Increasing wallet flexibility

In order to be able to do a wallet restore, the wallet hides some information in the bulletproofs of the outputs it creates. The proof generation uses a nonce, which is used to derive some of the secret values in the proof. Using this nonce a bulletproof can be rewound to obtain the hidden information.

In the default implementation the hidden information is the amount and the derivation path of the key. The nonce is calculated as hash(commit, root_secret_key). During a restore, a wallet has to attempt a rewind on each of the UTXOs, using the nonce. If succesful, it obtains the amount and derivation path, which tells us that the output belonged to us and how to derive the secret key from the seed.

However, there are two downsides to using this specific nonce.

  • It does not allow for "child wallets", i.e. multiple wallets that can be derived from the seed, where the parent can see and spend all the child wallet outputs but the child wallets themselves can only see/spend their own outputs. This is because calculating the nonce requires knowledge of root_secret_key, which effectively means that all child wallets have full access to all the funds, even from siblings.
  • Much for the same reason, watch-only wallets are not possible. It is not watch-only if you know the secret key, because it allows you to spend the outputs as well

Here are a couple of proposed fixes for this.

  • Use hash(commit, child_secret_key) as nonce. This would enable child wallets, but not watch-only. Moreover, a restore for the main wallet has to rewind each UTXO N times for N child wallets, which is more effort. And in most cases N might not even be known or remembered, which would force you to grind a very large number of them.
  • Use hash(commit, child_public_key) as nonce. This would make both child and watch-only wallets possible, but the grinding problem still exists.
  • Use hash(commit, root_public_key) or hash(commit, hash(root_secret_key)) as nonce. This would also enable both new wallet types, but now each child wallet has 2 values they need to have and keep private, namely their child_secret_key and the root_public_key. Leaking the latter will result in a loss of privacy. Furthermore the child wallets can "see" outputs of their siblings, which in some usecases might be undesirable.

None of the methods seem like a great solution, so I think we should spend some more time and try to come up with a better one. Of course wallet implementers are free to choose their own method of marking/restoring outputs, but it would be great if we could have a standard definition that does the job well enough that most wallets will just use it, making them compatible with each other.

Suggestions are very much welcome!

Non-interactive transactions seem lower-friction than interactive ones

Is your feature request related to a problem? Please describe.
Non-interactive transactions (e.g. Alice -> Bob) seem both plausible and lower-friction than the current Alice -> Bob -> Alice workflow.

Describe the solution you'd like
Alice wants to send to Bob, so instead of getting commitments from Bob, she creates her change output for herself and also picks all the private values Bob would have picked for his output. She completes the transaction.

Then, at some point in the future, Alice sends Bob all the secrets she chose for him, along with the output. Bob runs:

grin take-ownership <File containing the secrets Alice chose for Bob>
...which automatically creates a Grin transaction from the output Alice made for Bob to a new output that only Bob controls.

So two total transactions, but one less interaction needed between Alice and Bob. And, these two transactions would automatically condense on-chain, because they model an Alice -> Bob -> Charlie chain.

Describe alternatives you've considered
N/A

Additional context
The trust relationship in the existing Grin transaction model is exactly the same as in the one I am proposing. In my view, this proposal is strictly an optimization. Let's examine.

In my proposal, the risks are:

  1. Bob can try and take-ownership of the transaction, and see that the transaction has already been spent.
  2. Bob can try and take-ownership of the transaction, and see that the amount is not what he had hoped.
  3. Bob can try and take-ownership of the transaction, successfully collect the Grin, and claim he never received it.

All of these risks are present in the existing Alice -> Bob -> Alice interactive model. Why? Because everything relies on Alice anyway.

After receiving Bob's partial signature, Alice is the one who needs add her signature, and then broadcast the transaction. Bob can't!

Knowing this, the risks of the existing model are:

  1. Alice could never broadcast the transaction. At best, Bob can say "you didn't send me Grin!" and Alice could say "yes I did!". In a dispute like this, there is literally no way that Alice could prove she sent the Grin to Bob.
    --> Similarly, in my proposal, Bob could say "the blinding factor and output you sent me -- you already spent it!" and Alice could say "no I didn't!"
  2. Bob could successfully receive the Grin, yet still tell Alice "you didn't send that Grin to me -- you sent it to someone else/a blinding factor you control!"
    --> The same risk is present in my proposal.

API wallet/owner/retrieve_outputs doesn't return mmr_index of the outputs

Since a output commitment is only unique in the current UTXO set the wallet API should also provide correct mmr_indexs of all outputs to distinguish between outputs.

Steps to reproduce the behavior:

  1. Call retrieve_outputs on a Unspent output
  2. Expect the output to have a mmr_index
  3. The mmr_index is always null

version v1.0.1

The mmr_index is also not given via the cli command txs -i X

How to connect to grin node using windows wallet?

I have a node running on my Linux VM. When i connect from the Win client, i get a wrong response code error. I do not have this behavior if i run the wallet from the node itself. I checked my node and confirmed the api_http_addr was updated to 0.0.0.0. At this point i am not sure if it I am missing something in the server config file, or if something is wrong with the windows binary.

Error for reference:
C:\Users\xxx\Documents\Wallets\Grin>grin-wallet.exe -r http://192.168.1.111:3413 info
Password: 20190302 14:41:56.091 ERROR grin_refwallet::node_clients::http - Get chain height error: Request error: Wrong response code

Just a note, the node is fully sync'd.

Any help would be appreciated.

wallet owner_api takes up memory and keeps growing

Owner_api after running for a few days, the memory has been growing and has not been reduced.

Steps to reproduce the behavior:

  1. Run 'grin server run'
  2. Run 'grin wallet owner_api'
  3. Call the API in the document multiple times
    https://github.com/mimblewimble/grin/blob/master/doc/api/wallet_owner_api.md
  4. See the memory usage of the process

Screenshots
The memory usage when start owner_api
image

The memory usage after owner_api ran for one day
image

Version info:

  • OS: [debian:9.4]
  • Version [grin 1.0.0]

Validate full wallet balances like a block or UTXO set

There are multiple places in Grin where we validate that a set of commitments sum properly against a known value and a pubkey with a signature. A block has to sum against its coin inflation. A transaction against its fee. The full UTXO set against, the whole supply.

This concept can be extended to a wallet, to ensure all its unique unspent output commitments sum against the final balance. The wallet can produce the sum of all private keys as well, so the resulting pubkey can be validated either directly, or through a signature like everything else.

The objective is to have a full wallet validation that's hard to game or exploit, detecting or preventing bugs resulting in duplicate outputs, mutated outputs, etc. To be clear, this is a secondary measure (belt and suspenders again). I expect this would be very valuable to a exchanges or merchant services for example, that have to accept large amounts of externally-created transactions.

Term should output without colors if colors unavailable

Should I should handle errors when I perform "./grin --floonet wallet outputs", should I respond?

root@TX01:/data/grin# ./grin --floonet wallet outputs
Password:

20190108 19:32:37.286 ERROR grin_util::logger -
thread 'main' panicked at 'called Result::unwrap() on an Err value: ColorOutOfRange': libcore/result.rs:1009stack backtrace:
0: 0x55790812874d - backtrace::backtrace::trace::hd74837959dc31a2c
1: 0x557908127962 - <backtrace::capture::Backtrace as core::default::Default>::default::hfbe03539066da14f
2: 0x5579081279d9 - backtrace::capture::Backtrace::new::hd9d47426559d8b68
3: 0x5579080b8ae0 - grin_util::logger::send_panic_to_log::{{closure}}::h0919c24963251ad6
4: 0x5579081f8416 - std::panicking::rust_panic_with_hook::hde420d6fd4455550
at libstd/panicking.rs:480
5: 0x5579081f7f61 - std::panicking::continue_panic_fmt::h8f394f3c578bcc76
at libstd/panicking.rs:390
6: 0x5579081f7e45 - rust_begin_unwind
at libstd/panicking.rs:325
7: 0x557908241ebc - core::panicking::panic_fmt::hca5dc4e8b320bc56
at libcore/panicking.rs:77
8: 0x557907c0e6a9 - core::result::unwrap_failed::hfe0779afeaefd5ae
9: 0x557907bd0efb - grin_wallet::display::outputs::hdbc67f2895df033e
10: 0x557907a021c1 - grin_wallet::controller::owner_single_use::h13e0ae4138880dcc
11: 0x5579079abc48 - grin_wallet::command::outputs::hb0d7f9e779d5c519
12: 0x5579079a34ea - grin::cmd::wallet_args::wallet_command::h9588b7d4e2e05e87
13: 0x557907958dda - grin::cmd::wallet::wallet_command::h2fbcdf54a1f66b70
14: 0x5579079c2cab - grin::real_main::hb39a0190d567a13c
15: 0x5579079c1575 - grin::main::hab1e977be2785e7c
16: 0x557907992f52 - std::rt::lang_start::{{closure}}::h2873acc0c7532388
17: 0x5579081f7de2 - std::rt::lang_start_internal::{{closure}}::hafa8ecdacd368ebb
at libstd/rt.rs:59
- std::panicking::try::do_call::h8c0dbb48abbdf4df
at libstd/panicking.rs:310
18: 0x55790820a4b9 - __rust_maybe_catch_panic
at libpanic_unwind/lib.rs:102
19: 0x5579081d963a - std::panicking::try::hbc21637ba5f64d73
at libstd/panicking.rs:289
- std::panic::catch_unwind::h954917b922b8d970
at libstd/panic.rs:392
- std::rt::lang_start_internal::h5b2de3cc38c3b406
at libstd/rt.rs:58
20: 0x5579079c3b14 - main
21: 0x7f1a54e7d82f - __libc_start_main
22: 0x557907903a88 - _start
23: 0x0 -

Thread 'main' panicked with message:
"called Result::unwrap() on an Err value: ColorOutOfRange"

when

API Inconsistency between grin wallet info and retrieve_summary_info

Describe the bug

When sending grin, from the sender's perspective, there is an inconsistency between grin wallet info and the owner api retrieve_summary_info endpoint.

To Reproduce
Steps to reproduce the behavior:

  1. Send some grin to yourself using file, grin --floonet wallet send --method=file --dest=temp.json
  2. Receive the file grin --floonet wallet receive --input=temp.json
  3. Run grin --floonet wallet info note the UTXOs get locked up (that's good)
  4. Run curl -v -u grin:PASSWORD --request GET --url "http://127.0.0.1:13420/v1/wallet/owner/retrieve_summary_info?refresh=true" -H 'Content-Type: application/json' where PASSWORD is from the .api_secret file. Note the outputs are consistent.
  5. Finalize grin --floonet wallet finalize --input=temp.json.response
  6. Run grin --floonet wallet info again and note that nothing has changed
  7. Keep running the info command, note that once you get one confirm, the info command output changes (as it should) but the output from the curl command to the owner api goes IMMEDIATELY to spendable and does not wait for the change to settle. This inconsistency persists while the number of confirmations on the change is more than 1 and less than 10.

Desktop (please complete the following information):

  • OS: System Version: macOS 10.13.6 (17G4015) Kernel Version: Darwin 17.7.0
  • Version 1.0.1

Allow for recipient initiated transactions (invoices)

Is your feature request related to a problem? Please describe.
There should be a way for the recipient to initialize/finalize a transaction to facilitate online commerce (a la LN invoices), I see this feature requested frequently in gitter.

Describe the solution you'd like
Some ideas on how this could work on the UX level:

  • add a base64 serializer to the slate
  • add a grin wallet invoice subcommand with options --method (file or base64 for now) --destination and --message. Base64 method prints the encoded slate to stdout
  • add a grin wallet pay <string> subcommand (prints amount and message and asks for confirmation). This would return another b64 string

The merchant on checkout would print the b64 invoice and have a textarea where you paste your response.

Thoughts?

Request error: Cannot make request: parsed HTTP message from remote is incomplete

Describe the bug
After using grin and grin wallet check and doing some successful transfers, I'm unable to check my balance now with grin wallet check. I'm getting this error:

20190201 15:13:31.976 ERROR grin_wallet::node_clients::http - get_outputs_by_pmmr_index: unable to contact API http://127.0.0.1:3413. Error: Request error: Cannot make request: parsed HTTP message from remote is incomplete

To Reproduce
Steps to reproduce the behavior:

  1. Run 'grin wallet check'
  2. Expect data on my balance

win wallet custom path issues

Wallet dont follow 'grin server config'

If I manual edit and move wallet files to grin dir

It still create api here:

C:\Users\user\.grin\main\.api_secret

Read Only Wallet Database User and Read Only Wallet API

Is your feature request related to a problem? Please describe.
Currently, there's no solution for an auditor to read the wallet transaction log without giving the wallet password, or no solution for wallet API to have a read only right (no access for issue_send_tx for example).

Describe the solution you'd like
To be discussed.

Propose API for B2C payments and withdrawals

Currently we are more oriented to peer-to-peer payments even if we support http client/server interaction.
We may want a standardize API for B2C (Business to Customer) case which has the following properties:

  • Business is publicly available and can launch a listening socket on some port.
  • Customer can be behind NAT and can only initiate connections.
  • Customer can initiate payment
  • Customer can initiate withdrawal

We need this API be implemented in the wallet(s), server side will be specific to particular service, because it includes custom logic like customer balance checking, updating internal balance etc.

It would greatly improve user experience by enabling one-click (one command if you want) payments and withdrawals from any service which supports this API.

cancel_tx API does not free outputs

How to reproduce

Make a tx file through issue_send_tx, cancel that tx through cancel_tx, the output stuck at Awaiting Confirmation

txs

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Id  Type         Shared Transaction Id                 Creation Time        Confirmed?  Confirmation Time    Num.    Num.     Amount    Amount   Fee    Net         Tx  
                                                                                                              Inputs  Outputs  Credited  Debited         Difference  Data 
=================================================================================================================================================================================================================
 0   Received Tx  None                                  2019-01-11 05:35:20  true        2019-01-11 05:35:20  0       1        0.1       0.0      None   0.1         None 
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 1   Sent Tx      3fb84749-f5c7-4625-a955-0c4d36ce2dd5  2019-01-11 11:18:23  true        2019-01-11 11:34:52  1       1        0.082     0.1      0.008  -0.018      3fb84749-f5c7-4625-a955-0c4d36ce2dd5.grintx 
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2   Sent Tx      42de1d56-30f3-493e-ab3e-e1baa55c52d4  2019-01-12 05:19:04  false       None                 1       1        0.064     0.082    0.008  -0.018      42de1d56-30f3-493e-ab3e-e1baa55c52d4.grintx 
     - Cancelled                                                                                                                                                      
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

summary

[
  true,
  {
    "last_confirmed_height": 21022,
    "minimum_confirmations": 1,
    "total": 82000000,
    "amount_awaiting_confirmation": 82000000,
    "amount_immature": 0,
    "amount_currently_spendable": 0,
    "amount_locked": 0
  }
]

introduce progress indicator for `grin wallet restore`

Currently, grin wallet restore progress is bit of a mystery for the user. No indication of how long it takes to complete a restore, nor whether the wallet is actually working on something or not.

It would be useful to see some kind of progress indicator, even the most rudimentary version, to indicate that the restore process is not just stuck somewhere.

Wallet transaction privacy enhancement

Currently, we're putting the transparent coin amount, fee, height/lock_height, and so on in the slate, and fully rely / depend on the communication channel to manage / provide the privacy, such as via the Https / Keybase for encrypted communication channel, or via the Http / File which can't provide privacy.

This is a quite reasonable/good design, to provide multiple methods on low level, and the developers / users MUST know what they're doing.

For example, in a safe private network, using Http for internal wallet transaction could not be a bad design.

But I indeed have a little worry that actually we should do a little bit more here to protect our privacy reputation, since privacy is the brand of Mimblewimble protocol.

And a possible worse situation is some people (especially those without much IT knowledge background) could simply use the Http for grin wallet send, since it's much simple than the Https setup. For example, someone send some grin coins to a friend from a company network, and the network admin come to warn him/her don't play crypto in the office and even says "wow you're so rich~ you sent 1 million grin coins! how much coins do you have?" then that someone will be shocked and faint 😸 he/she could have expected privacy cryptocurrency must 100% privacy! in any situation! then the Grin privacy reputation will turn into dusky among persons in the street, by such kind of misuse.

Why not kill this risk at day one of our launching 😄

To give a shot on what these transparent slate looks like:

{
   "num_participants":2,
   "id":"37453d70-85c7-432b-b880-f909b06f4e82”,\
   "tx":{...
      "kernels":[\
         {  "features":{"bits":0},\
            "fee":8000000,\
            "lock_height":89165,\
            "excess":[...],\
            "excess_sig":[...]\
         }]\
      }\
   }
   "amount":1000000000,\
   "fee":8000000,\
   "height":89165,\
   "lock_height":89165,\
   "participant_data":[\
   {  "id":0,\
      "public_blind_excess":[3,241,235,206,70,87,156,16,145,214,145,129,220,233,235,214,243,246,31,66,78,99,34,30,19,216,32,14,202,178,4,205,100],\
      "public_nonce":[2,246,65,150,75,199,223,145,67,54,165,74,244,234,7,129,57,5,9,40,193,125,54,141,50,146,148,177,153,106,214,150,140],\
      "part_sig":null,\
      "message":null,\
      "message_sig":null\
   }\
   ]\
}

So, I propose we do a global transaction data encryption as the grin wallet default implementation, at our low level, and never rely on the communication channel to provide this.

Before go inside the detail design of this (should be easy to implement and can be completed in one/two days), I would like to hear from you if this is really matter and needed.

Wallet DOS/Spam Protection

Right now it's trivial to spam a wallet listener with millions of fake transactions, causing it to create spam outputs and creating a lot of hassle for the wallet owner. This needs to be mitigated somehow, probably starting with simple banning misbehaving IPs but will definitely need to become more foolproof.

wallet database read empty

With same wallet database, the grin wallet info read it as:

 Total                            | 0.498200000 
 Awaiting Confirmation (< 10)     | 0.000000000 
 Locked by previous transaction   | 0.000000000 
 -------------------------------- | ------------- 
 Currently Spendable              | 0.498200000 

but the grin-wallet info read it as:

 Total                            | 0.000000000 
 Awaiting Confirmation (< 10)     | 0.000000000 
 Locked by previous transaction   | 0.000000000 
 -------------------------------- | ------------- 
 Currently Spendable              | 0.000000000 

Reverting the version and find the commit 6a196f is ok.
problem start from 27th Feb. "updates based on upstream”, the wallet database read out empty.

Does the grin_store import this incompatible?

- "grin_store 1.0.1 
+ "grin_store 1.1.0

Transaction Fee Calculation

https://gitter.im/grin_community/dev?at=5c1e24a537975e7ca90957e4

John Tromp @tromp 19:54
i don't understand why we don't base fee on weight_as_block()

Gary Yu @garyyu 20:12
If using weight_as_block(), the tx fee will be greatly increased.
weight = max( output_len * 4 + kernel_len - input_len , 1)
VS
weight = ( output_len * 21 + kernel_len * 3 + input_len )
Should we worry the transaction fee is too expensive?
in a normal tx case of 1 input 2 output, it’s 8mg VS 46mg, if I calculate correct.

jaspervdm @jaspervdm 20:15
i like the negative weight for inputs on the fee, it promotes utxo consolidation

Gary Yu @garyyu 20:16
yes, it encourge merge UTXOs

John Tromp @tromp 21:18
@jaspervdm @garyyu what's better at minimizing utxo set size: penalizing their creation, or encouraging their destruction?
where latter is even limited by the max(,1)
and where former is incentive compatible with miners selecting tx to include in block

please add --txid to the `wallet txs` command

Currently the wallet txs command only accepts a transaction index number with -i $index, which makes things cumbersome. What we know is the txid, and in order to see the outputs, then right now I have to first list all transactions with wallet txs then parse the list to find the txid, then and fetch its $index, then run wallet txs -i $index. Adding --txid can remove the intermediary steps so I can see the outputs easily.

Could that be added please?

transaction error

Describe the bug
I have two nodes,but when I send some grin to other...

To Reproduce
Steps to reproduce the behavior:
send : run grin wallet txs
73 Sent Tx 77862d46-cff4-4572-89a1-b4689c18c33c 2019-02-21 07:34:56 false None
74 Sent Tx a48216e6-7fdf-483e-9d36-0499f68cb160 2019-02-21 07:35:03 false None
75 Sent Tx 8af931df-ca06-4911-9adc-9f6b6168f014 2019-02-21 07:35:11 true 2019-02-21 07:41:08

recevied : run grin wallet txs
61 Received Tx 77862d46-cff4-4572-89a1-b4689c18c33c 2019-02-21 07:34:56 true 2019-02-21 07:40:48
62 Received Tx a48216e6-7fdf-483e-9d36-0499f68cb160 2019-02-21 07:35:03 true 2019-02-21 07:40:48
63 Received Tx 8af931df-ca06-4911-9adc-9f6b6168f014 2019-02-21 07:35:11 true 2019-02-21 07:40:48

It's very strange that the sender's transaction has never been confirmed.

Mechanism to prove UTXO ownership to third-party

Businesses that use Grin for transactions will have to prove to auditors their current balance, incoming transactions, and outgoing transactions. This is crucial for taxpaying entities to use Grin or any other currency. Other privacy coins such as Monero have this capability through view-only keys and send proofs.

In the gitter chat, @jaspervdm said:

you can prove you are in posession (ie you own UTXOs) of a specific amount, yes, by signing a message with your blinding factor(s). it is however currently not possible with the wallet

Having a wallet feature do this would be ideal, but even without that, the mathematics of how to accomplish this documented would be the bare minimum requirement for a business.

For a third-party auditor with the full blockchain archive synced, the business needs a way to prove these (without giving the third-party the private key):

  • Prove current balance (which unspent UTXOs we own)
  • Prove incoming transactions (receives)
  • Prove outgoing transactions (sends)

Obviously the addresses we receive from or send to don't exist, but the change of UTXO ownership happens in a block height which itself has a timestamp.

Deprecate http listener for external addresses

Deprecate http listeners for external addresses due to it being insecure and exposing the transacting parties to unnecessarily easy attacks.

Blocked until a convincing better alternative is proposed for transaction building.


Apr 02 2020 edit: Renaming and editing description and using to track for v4.0.0

owner_api_include_foreign doesn't work with usernet

When running a usernet wallet with the config flag owner_api_include_foreign = true.
The grin daemon (started also with usernet)is not able to mine to the wallet.

Usernet mining works when I run the listen command alone with owner_api_include_foreign = false.

Steps to reproduce the behavior:

  1. Set the wallet usernet config to owner_api_include_foreign = true
  2. Set the server usernet config to run_test_miner = true and test_miner_wallet_url = "http://127.0.0.1:13420"
  3. Start the wallet with grin --usernet wallet -p xxx owner_api
  4. Start the node with grin --usernet

The logs show that both owner_api and listen api are running on the same port.
When I run the wallet with owner_api_include_foreign = true I tested other owner_api calls and they where working. I didn't test the foreign api.

Build from tag v1.0.0.

Add wallet initialization api to owner api?

It will be much convenient for third-part developer(like web wallet developer) to add a wallet initialization api to owner api.

This api should have the same function like command "grin wallet init"
Api user could post password and return 24 word recovery phrase if wallet is initialized successfully.

thanks.

Provable Interactive Transaction

RECENT CHANGES:

  • (6 Mar 2019) Combine the pubkey and destination fields, according to @jaspervdm 's comment.
  • (5 Mar 2019) Creation.

Table of Contents

1. Use case

1.1 In Bitcoin

In the Bitcoin transaction scenario, Bob tell Alice his Bitcoin address, for example: 3ChVP627..., and Alice do a Bitcoin transaction to pay to this address, for example: 3169d1b5..., and the HASH160 form of this address is directly put on the public chain database (as the Output Scripts): HASH160 PUSHDATA(20)[78c04dda49b06260020a106f8e279b1bfbadcb71] EQUAL.

This is a perfect provable transaction, since there's no way for Bob to deny he received this payment.

1.2 In Grin

In the Grin transaction scenario, Bob tell Alice his Grin wallet address, for example: https://bob.grinwallet.me:3415, and Alice do a Grin transaction to pay to Bob's said wallet. Once the transaction is done and confirmed on the chain, Bob has his UTXO on the chain, for example: 0861105a....

But the practical problem is: there's no any public indicator on the chain which can prove this output belongs to Bob. ONLY Bob can prove this output belongs to himself, nobody else without Bob's private key!

So, in case Bob deny he received Alice's payment, it will be very complex for Alice to prove she paid, and even impossible if she can't force Bob to provide related evidence.

2. Provable Interactive Transaction solution

## 2.1 Recap of Grin current slate structure in the Interactive Transaction

Let's take a look at an example of a finalized slate (of a wallet transaction):

{
  "num_participants": 2,
  "id": "8ba033b6-3e05-4cad-81ec-937f3056b1e8",
  "tx": {
    "offset": [...],
    "body": {
      "inputs": [
        {
          "features": "Plain",
          "commit": [...],
        }
      ],
      "outputs": [
        {
          "features": "Plain",
          "commit": [...],
          "proof": [...],
        },
        {
          "features": "Plain",
          "commit": [...],
          "proof": [...],
       }
      ],
      "kernels": [
        {
          "features": "HeightLocked",
          "fee": 8000000,
          "lock_height": 18187,
          "excess": [...],
          "excess_sig": [...],
       }
      ]
    }
  },
  "amount": 110000000,
  "fee": 8000000,
  "height": 18187,
  "lock_height": 18187,
  "participant_data": [
    {
      "id": 0,
      "public_blind_excess": [...],
      "public_nonce": [...],
      "part_sig": [...],
      "message": null,
      "message_sig": null
    },
    {
      "id": 1,
      "public_blind_excess": [...],
      "public_nonce": [...],
      "part_sig": [...],
      "message": null,
      "message_sig": null
     }
  ]
}

For the detail meaning of this structure, please refer to https://github.com/mimblewimble/grin/blob/391e311f4c05619bd4b7b0d599a5071ce7753b90/wallet/src/libwallet/slate.rs#L104:L127

2.2 Enhance Grin transaction as a provable transaction

The basic idea is to import the exact same "address" concept as Bitcoin, but only use it on the Grin transaction, not on the chain.

Still with above example slate, but with the enhanced fields:

{
  "num_participants": 2,
  "id": "8ba033b6-3e05-4cad-81ec-937f3056b1e8",
  "tx": {
    "offset": [...],
    "body": {
    (exact same as the original format)
    }
  },
  "amount": 110000000,
  "fee": 8000000,
  "height": 18187,
  "lock_height": 18187,
  "participant_data": [
    {
      "id": 0,
      "public_blind_excess": [...],
      "public_nonce": [...],
      "part_sig": [...],
      "message": null,
      "message_sig": null,
+     "p2pkh_dest": null,
+     "p2pkh_public_key": null,
+     "p2pkh_msg": [...],
+     "p2pkh_sig": [...]
    },
    {
      "id": 1,
      "public_blind_excess": [...],
      "public_nonce": [...],
      "part_sig": [...],
      "message": null,
      "message_sig": null,
+      "p2pkh_dest": [https://addr@hostname:port],
+      "p2pkh_public_key": [...],
+      "p2pkh_msg": [...],
+      "p2pkh_sig": [...]
     }
  ]
}

Note: p2pkh_dest can be https://addr@hostname:port, or keybase://addr@username, or other transport method/s.

Here is the proposal for this provable Grin transaction procedure.

2.2.1 Wallet URL with the receiver's "address"

For example, when Bob tell Alice his Grin wallet address, he give both his wallet URL and his "address": https://[email protected]:3415.

This "address" has exact same format as Bitcoin's legacy address.

2.2.2 Step 1: Alice send Bob a slate

{
  "num_participants": 2,
  "id": "8ba033b6-3e05-4cad-81ec-937f3056b1e8",
  "tx": {
    "offset": [...],
    "body": {
    (exact same as the original format and content)
    }
  },
  "amount": 110000000,
  "fee": 8000000,
  "height": 18187,
  "lock_height": 18187,
  "participant_data": [
    {
      "id": 0,
      "public_blind_excess": [...],
      "public_nonce": [...],
      "part_sig":  null,
      "message": null,
      "message_sig": null,
+     "p2pkh_dest": null,
+     "p2pkh_public_key": null,
+     "p2pkh_msg": [...],
+     "p2pkh_sig": [...]
    }
  ]
}

As the sender / payer, Alice:

  • leave p2pkh_public_key and p2pkh_dest as null
  • put the p2pkh_msg as the HASH of this slate data (exclude p2pkh_* and all other participant_data array elements, and exclude id)
  • and put p2pkh_sig as the signature of this p2pkh_msg with the private key related to public_blind_excess.

Note: Alice must keep the told Bob's p2pkh_dest at somewhere, and need to use them in the 3rd step.

2.2.3 Step 2: Bob receive above slate and send back the processed slate to Alice

Note: for security, Bob need check the received payment request whether his own "address" is there. If no, giving warning at this moment for compatibility of old version, and in the future we close the connection or ban the sender's IP in this case.

{
  "num_participants": 2,
  "id": "8ba033b6-3e05-4cad-81ec-937f3056b1e8",
  "tx": {
    "offset": [...],
    "body": {
    (exact same as the original format and content)
    }
  },
  "amount": 110000000,
  "fee": 8000000,
  "height": 18187,
  "lock_height": 18187,
  "participant_data": [
    {
      "id": 0,
      (same data as above received slate)
    },
    {
      "id": 1,
      "public_blind_excess": [...],
      "public_nonce": [...],
      "part_sig": [...],
      "message": null,
      "message_sig": null,
+      "p2pkh_dest": [3ChVP627KU5w4zu2rieFPF3wGXWQgmhvrs@https://bob.grinwallet.me:3415],
+      "p2pkh_public_key": [...],
+      "p2pkh_msg": [...],
+      "p2pkh_sig": [...]
     }
  ]
}

As the receiver / payee, Bob:

  • must put the correct p2pkh_dest which must be exact same as what he told Alice for this payment, and address as the 1st part of this p2pkh_dest
  • put p2pkh_public_key as the one which match the address
  • put the p2pkh_msg as the HASH of this slate data (exclude p2pkh_* and all other participant_data array elements, and exclude id)
  • and put p2pkh_sig as the signature of this p2pkh_msg with the private key related to p2pkh_public_key.

2.2.4 Step 3: Alice receive above slate and generate a finalized slate

{
  "num_participants": 2,
  "id": "8ba033b6-3e05-4cad-81ec-937f3056b1e8",
  "tx": {
    "offset": [...],
    "body": {
    (exact same as the original format and content)
    }
  },
  "amount": 110000000,
  "fee": 8000000,
  "height": 18187,
  "lock_height": 18187,
  "participant_data": [
    {
      "id": 0,
      "public_blind_excess": [...],
      "public_nonce": [...],
+     "part_sig": [...],
      "message": null,
      "message_sig": null,
      "p2pkh_dest": null,
      "p2pkh_public_key": null,
+     "p2pkh_msg": [...],
+     "p2pkh_sig": [...]
    },
    {
      "id": 1,
      (same data as above received slate)
     }
  ]
}

As the sender / payer, Alice:

  • must check the above received slate for the p2pkh_dest, which must be exact same as what she was told by Bob for this payment
  • must check the address is indeed generated by p2pkh_public_key
  • create her own partial signature for this transaction and update the tx body
  • update her p2pkh_msg and p2pkh_sig
  • keep this finalized slate stored at her wallet database, for any possible "provable" request in the future.

2.2.5 Finish

Alice post this transaction to the chain and this transaction will be confirmed at a few minutes.

2.3 Alice prove she did this transaction

For example, Bob deny and say he never receive this transaction from Alice.

Alice show / publish her saved finalized slate for this transaction, to Bob or any other 3rd party, anyone can validate this data and confirm Bob's lying, since this slate include Bob's address and Bob's signature, and the integrity checking.

3.Grin "address" generation

Since we already have BIP-32 HD wallet feature, it should be an easy point to have this / these "address"/es.

Btw, to support the new "address"/es, Grin wallet need to store all published / used "address", to enable the checking of any receiving payment requests, either on current "address" or on any previous "address".

4.Other use cases

I'm thinking it seems possible to share the wallet database with the auditor/s, without telling the wallet seed / private key. The auditor/s still can get the logs which can be easily validated. To be discussed with a separated issue / topic.

5.Validation API

We need some new API to enable an easy validation on this "provable" slate.

Welcome your review and any comments :-)
Especially for the security level with this solution. Please feel free to correct me if any mistakes

LMDBWallet Password Stored in memory

Around here, we need a better way of dealing with how the password is stored:

https://github.com/mimblewimble/grin/blob/eebc2b208ecfefb1a845d643ca7ec4e7348e61b2/wallet/src/lmdb_wallet.rs#L104

During most command-line operations,open_with_credentials is called tht loads the wallet keychain using the stored password credentials, performs the operation, then calls close which unloads the keychain data.

This model doesn't work for operations that open and close the wallet multiple times (there are a few), or for the owner API, where there is a resident listener process continually opening and closing the wallet for each operation.

Mitigate wallet output generation spam attack

Currently, grin wallets can be forced to generate many derived keys if an attacker repeatedly connects and completes just enough of the transaction construction process, but does not send an actual transaction.

A wallet that suffers from this attack will have to test a great number of derived keys every block in order to look for owned outputs. When restoring the wallet from its seed, it may also appear that the user has lost funds. The restore command only checks a relatively small number of derived keys for owned outputs, currently 1000 by default, so it will not find legitimate transactions that are owned by a derived key proceeded in the derivation sequence by 1000 spam-generated keys with no transactions.

This was discussed a little bit in chat.

Some possible mitigations:

  • Rate-limit payments
  • Require PoW on each payment
  • Come up with an improvement to the current O(M blocks * N derived keys) lookup algorithm

Is it an issue if a wallet reuses a derived key for a payment? If not, then a wallet might only advance to the next key in the sequence if it sees a mined transaction sent to the current key.

Integration test via http endpoints

Grin wallet should have integration tests for all exposed http endpoints in private and owner_api. This integration test should stand up a local network, set up two wallets, transfer new grins from one wallet into another and back.

This integration test will exercise a large amount of the code and can hopefully avoid issues such as #2105

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.