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

Subaddresses #2056

Merged
merged 1 commit into from Oct 15, 2017

Conversation

@kenshi84
Contributor

kenshi84 commented May 30, 2017

Note: This PR replaces #1753. Most importantly, the idea of disposable addresses was dropped, due to its potential danger of being misused by uneducated users which leads to on-chain tx linkability. See the relevant discussion here.

GUI version

1. Motivation

Suppose you publish a Monero wallet address for donation on your Twitter/etc profile page. Furthermore, you have an anonymous identity for some secret project where you also want to receive donation in Monero. Because you don't want people to be able to associate you with that anonymous identity by Googling your address, you'd want to use separate wallet addresses for these two purposes. While you can easily do so by simply creating two wallets separately, you're going to spend twice the time for scanning the blockchain and need twice the storage for the wallet cache. And this cost grows in proportion to the number of additional wallet addresses you'd like to have.

Another relevant scenario is when you want to buy Monero anonymously through ShapeShift. If you used the same Monero address repeatedly for multiple purchases, ShapeShift would know that the same person bought that much of Monero through those purchases (although they don't know your contact info as they don't require account registration). You can anonymize the process by creating a temporary wallet for every purchase and transferring the fund to your real wallet afterwards. This is doable, but clearly tedious.

The scheme proposed in this PR provides an effective solution for such scenarios, where the recipient can create multiple wallet "subaddresses" that appear unrelated to each other to outside observers, and the recipient can recognize all incoming transfers to those subaddresses with almost no additional cost. Note that this scheme only introduces additional procedures for the wallet software to construct and interpret transactions, while not requiring any change in the consensus rule (thus requiring no hard fork).

2. How it works cryptographically

Suppose Bob's wallet address is (A, B) = (a*G, b*G) where a and b are his view and spend secret keys, respectively. Likewise, Alice's address is (X, Y) = (x*G, y*G). Bob is receiving Monero from Alice, but he wants to do so without using his real address (A, B) in order to prevent Alice from knowing that the recipient is him. In the above example with ShapeShift, Bob would be you and Alice would be ShapeShift.

2.1. Generating a subaddress

Bob generates his i-th subaddress (i=1,2,...) as a pair of public keys (C,D) where:

m = Hs(a || i)
M = m*G
D = B + M
C = a*D

We call i the index of the subaddress. Note that (A,B) and (C,D) are unlinkable without the knowledge of the view secret key a. Bob then registers D to a hash table T stored in his wallet cache (akin to the aggregate addresses scheme):

T[D] <- i

To handle his main address in a unified way, Bob also registers B to the hash table:

T[B] <- 0

In other words, the index 0 is treated as a special case in this scheme representing the original standard address.

2.2. Sending to a subaddress

When Alice constructs a transaction that transfers some fund to a subaddress (C, D), she first chooses a random scalar s and generates a tx pubkey:

R = s*D

Note that the tx secret key r such that R = r*G is unknown to Alice because she doesn't know the secret key of D. She then computes an output pubkey for the destination:

P = Hs(s*C)*G + D

She finally computes an output pubkey to herself as her change:

Q = Hs(x*R)*G + Y

Importantly, without the knowledge of the tx secret key r as explained above, Alice can include her change output in the transaction only because she knows her own view secret key x. In other words, only single-destination transfers are possible in this scheme, and multi-destination transfers (e.g. pool payouts) require the use of standard addresses. (2017-08-01) Now this scheme supports multi-destination transfers by introducing additional tx keys.

Also note that Alice can prove her payment to Bob by using s.

2.3. Receiving by a subaddress

Bob checks if an output pubkey P in a new transaction belongs to him or not by computing

D' = P - Hs(a*R)*G

and looking for D' in the hash table. If the transaction was indeed bound to Bob's subaddress (C,D), D' should equal to D because

a*R = a*s*D
    = s*a*D
    = s*C

Therefore, Bob should be able to find D' in the hash table:

i <- T[D']

and obtain the private key of P:

p = { Hs(a*R) + b                   i == 0
    { Hs(a*R) + b + Hs(a || i)      otherwise

2.4. Grouping subaddresses

When sending funds to Bob's subaddress (C,D), Alice can choose to send the change to her i-th subaddress (X_i,Y_i) instead of her main address (X,Y) by replacing Y with Y_i when deriving the change's output pubkey:

Q = Hs(x*R)*G + Y_i

Using this scheme, it's now possible to maintain balances of subaddresses separately, making them virtually function as separate wallets. In order to maintain subaddresses in an organized manner, we propose a simple scheme of grouping subaddresses as follows: we define the index of subaddresses as a pair of indices (i,j) with i, the major index, representing a group of subaddresses (called an account) and j, the minor index, representing a particular subaddress within that account. Incoming transfers to subaddresses belonging to the same account (i,0), (i,1), ... are summed up to form a single balance, and any spending of those outputs will transfer the change to the base subaddress (i,0). The index (0,0) represents the original standard address.

3. How it works in the CLI

3.1. Synopsis

Existing commands with updated syntax:

address
address new <label text with white spaces allowed>
address all
address <index_min> [<index_max>]
address label <index> <label text with white spaces allowed>

balance [detail]

show_transfers [in|out|pending|failed|pool] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]]
incoming_transfers [available|unavailable] [index=<N1>[,<N2>,...]]
unspent_outputs [index=<N1>[,<N2>,...]] [<min_amount> [<max_amount>]]

transfer [index=<N1>[,<N2>,...]] [<priority>] [<mixin_count>] <address> <amount> [<payment_id>]
locked_transfer [index=<N1>[,<N2>,...]] [<priority>] [<mixin_count>] <addr> <amount> <lockblocks> [<payment_id>]
donate [index=<N1>[,<N2>,...]] [<priority>] [<mixin_count>] <amount> [<payment_id>]

sweep_all [index=<N1>[,<N2>,...]] [<mixin_count>] <address> [<payment_id>]
sweep_below <amount_threshold> [index=<N1>[,<N2>,...]] [<mixin_count>] address [<payment_id>]

New commands:

account
account new <label text with white spaces allowed>
account switch <index>
account label <index> <label text with white spaces allowed>

3.2. Managing accounts

Initially, the wallet has only one account corresponding to the major index 0. The account index is indicated as the number after / in the command prompt:

[wallet/0 9uPkEU]: 

You can create a new account by using the command account new:

account new <label text with white spaces allowed>
[wallet/0 9uPkEU]: account new eBay selling   
        Account               Balance      Unlocked balance                 Label
       0 9uPkEU        0.000000000000        0.000000000000               Default
       1 Bd2qqa        0.000000000000        0.000000000000          eBay selling
----------------------------------------------------------------------------------
          Total        0.000000000000        0.000000000000

[wallet/1 Bd2qqa]: address
0  Bd2qqam2EKc8NRzTYg9QPJZ81Ey1WRp1Bcnmjzf28K3edRyr1rcLbjiQZdR7tsuTUJBahi32RSDb1cuqsACaEDwGRMZ4Eaa  eBay selling

Note the change of the address. The command account switch lets you switch between accounts:

[wallet/1 Bd2qqa]: account switch 0
Currently selected account: [0] Default
Balance: 0.000000000000, unlocked balance: 0.000000000000

[wallet/0 9uPkEU]: address
0  9uPkEUFcFujaw1YCDHhcvuUqQm9cGBBuu5KkGggFR9XMjQtXtFzUDbRU9oy4XYer9SeaSGAhtoT1xDsBuVDRqfg9GG2ji9U  Default

The command account with no arguments shows the list of all the accounts along with their balances:

[wallet/0 9uPkEU]: account
        Account               Balance      Unlocked balance                 Label
       0 9uPkEU        0.000000000000        0.000000000000               Default
       1 Bd2qqa        0.000000000000        0.000000000000          eBay selling
----------------------------------------------------------------------------------
          Total        0.000000000000        0.000000000000

At any time, the user operates on the currently selected account and specifies the minor index in various commands when necessary via the index parameter; i.e. in the following description, we use the term "index" to mean the minor index.

3.3. Generating subaddresses

The command address shows the "base" address at index=0 (which corresponds to the original standard address when the currently selected account is at index=0). The command address new lets you create a new address at one index beyond the currently existing highest index associated with this account. You can assign a label to the address if necessary:

address new <label text with white spaces allowed>
[wallet/0 9uPkEU]: address new ShapeShift purchase on 2017-Jul-08
1  BZ9PfXYboScf2vs4EcnMBdT2dvzmE1hLnZixxnmAP2vs52jQiLTmDzTDhdwVyuBWMhCeiTxD4bVCJipsfmGxtBTwSq4HwAh  ShapeShift purchase on 2017-Jul-08

Note that this command is intended to be used for generating "throwaway" addresses; i.e. when you just want a fresh new address to receive funds to the currently selected account (e.g. when purchasing XMR through ShapeShift). If instead you want to maintain a separate balance associated with a new address, create a new account by the command account new.

The commands address all and address <index_min> [<index_max>] show lists of addresses that have been generated so far:

[wallet/0 9uPkEU]: address all
0  9uPkEUFcFujaw1YCDHhcvuUqQm9cGBBuu5KkGggFR9XMjQtXtFzUDbRU9oy4XYer9SeaSGAhtoT1xDsBuVDRqfg9GG2ji9U  Default
1  BZ9PfXYboScf2vs4EcnMBdT2dvzmE1hLnZixxnmAP2vs52jQiLTmDzTDhdwVyuBWMhCeiTxD4bVCJipsfmGxtBTwSq4HwAh  ShapeShift purchase on 2017-Jul-08
2  BfhF533yqmNfxfgoDXK1411DYveWMU1xRQzMPPpHVrZgeoCoVrQ9GCjY1mvDQQaoiCZYhKhGVHLkm51cgZYfDUpt5Bw4ZgB  ShapeShift purchase on 2017-Jul-09
3  BhTfiQY1Xj6AKXPUtDbunJPmqrbkha5qvNgYoipp6L7FQ8KTDciDWjF3YQ5g2dCLNLjJoUEJKVeYt9Rpb8tgDzT36fSoS9D  
4  BYoaHkHjFEY371Jq9fY9x9TJjaMeDXBYS9AfqCJ7SJoe5vuJLDPsyhU3RzDFNXKkEqBDqQMX1bDuUQbXKXctTGXY9ZgdGa1  ShapeShift purchase on 2017-Jul-11
5  BcxioZpKqYaZsSDHP6pmesaV7gMrPYxvHXsnkG5ceVGkasPR83cEJyvGNpckYvs2wP76HsM1KGo1mbEmmiburnCUT4aSEv1  ShapeShift purchase on 2017-Jul-13
6  BZzdxkqM8fJhZLATeyD3bd2cSrehGsANH4CgyJ4DBUamJAdyRTqkZ1W3kvN1UpzLz1iQU8XfEQUi15QyobFyMQVb3LDj4gZ  ShapeShift purchase on 2017-Jul-17
7  BYNUQQfEtg2gshraM8RPGvPUNbWcHHu33Tzhxy8ZrL7r7MYDkdPUCDFYxNawBNSAdjhKUCsiWjg5tQoReRMKGQ1fJS2QuEB  ShapeShift purchase on 2017-Jul-21

[wallet/0 9uPkEU]: address 3 6
3  BhTfiQY1Xj6AKXPUtDbunJPmqrbkha5qvNgYoipp6L7FQ8KTDciDWjF3YQ5g2dCLNLjJoUEJKVeYt9Rpb8tgDzT36fSoS9D  
4  BYoaHkHjFEY371Jq9fY9x9TJjaMeDXBYS9AfqCJ7SJoe5vuJLDPsyhU3RzDFNXKkEqBDqQMX1bDuUQbXKXctTGXY9ZgdGa1  ShapeShift purchase on 2017-Jul-11
5  BcxioZpKqYaZsSDHP6pmesaV7gMrPYxvHXsnkG5ceVGkasPR83cEJyvGNpckYvs2wP76HsM1KGo1mbEmmiburnCUT4aSEv1  ShapeShift purchase on 2017-Jul-13
6  BZzdxkqM8fJhZLATeyD3bd2cSrehGsANH4CgyJ4DBUamJAdyRTqkZ1W3kvN1UpzLz1iQU8XfEQUi15QyobFyMQVb3LDj4gZ  ShapeShift purchase on 2017-Jul-17

The command integrated_address also takes an optional argument to specify the index:
(2017-08-01) The integrated subaddresses format was dropped as subaddresses are expected to be replacing the role of payment IDs

The command address label lets you set the label of an address:

address label <index> <label text with white spaces allowed>
[wallet/0 9uPkEU]: address label 3 test test
3  BhTfiQY1Xj6AKXPUtDbunJPmqrbkha5qvNgYoipp6L7FQ8KTDciDWjF3YQ5g2dCLNLjJoUEJKVeYt9Rpb8tgDzT36fSoS9D  test test

Note that the label of the base address is treated as the label of the currently selected account. You can change account labels by using either address label or account label:

[wallet/0 9uPkEU]: address label 0 My home account  
0  9uPkEUFcFujaw1YCDHhcvuUqQm9cGBBuu5KkGggFR9XMjQtXtFzUDbRU9oy4XYer9SeaSGAhtoT1xDsBuVDRqfg9GG2ji9U  My home account

[wallet/0 9uPkEU]: account label 1 My secret business account
        Account               Balance      Unlocked balance                 Label
       0 9uPkEU        0.000000000000        0.000000000000       My home account
       1 Bd2qqa        0.000000000000        0.000000000000 My secret business account
----------------------------------------------------------------------------------
          Total        0.000000000000        0.000000000000

3.4. Checking funds and balances

Here the wallet finds a few incoming transfers by some of its subaddresses (indicated by the major-minor index pairs):

Height 949115, txid <2c9d55d65f67243f771729ecd93a089ca0fcde3451f5a7740a4df70d8240b95b>, 0.130000000000 XMR, idx 0/1
Height 949115, txid <68ee8848bbb953e3a0bc8d3175e8724c3fb04cd2e49244c76d26d5b2fa2a6da2>, 0.020000000000 XMR, idx 0/0
Height 949115, txid <01f3865e63613413f6de4d4cd2b2638b679aa604c06299ad4b562364afc8cf5a>, 0.110000000000 XMR, idx 0/1
Height 949115, txid <b3bd13988448ef3bb95e6f3bf007f42ebc4f0d21346b6c4d45e42d53caa3e297>, 0.120000000000 XMR, idx 0/1
Height 949115, txid <05a97709858358ec8bb008cc8ad7f70e35ec07219cc8744138473200bb9922ec>, 0.230000000000 XMR, idx 0/2
Height 949115, txid <9a1527acdce60bbe38c8c7e9d3bfe894108d5b30eb630904a3b3afd5059b3344>, 0.210000000000 XMR, idx 0/2
Height 949115, txid <6716c0707b4c198777adbcda6b630b6248ef07fb86d20ba4469dcf661f5b35ee>, 0.010000000000 XMR, idx 0/0
Height 949115, txid <04bf1d9a5b8b3fe74d26bd068844f4709b22c92f6a3b5594f217c22df88f8184>, 0.030000000000 XMR, idx 0/0
Height 949115, txid <02b76b48467a806c6e45ce6fdf59df3c694f857f450a450537a9769f911fee46>, 0.220000000000 XMR, idx 0/2
Height 949116, txid <92f3b54a3044eddf3fd84742852f8a81b55e92055281c945bd7dee85e589ccc2>, 1.010000000000 XMR, idx 1/0
Height 949117, txid <d2617a1da91203247f8b904cf05906973cc9a64bff8d6ab4d956f22cb5d5271e>, 1.030000000000 XMR, idx 1/0
Height 949117, txid <441b07d91f64adf1b4f8350ca33902ed4aab306df3f66e1673d35a151186140c>, 1.020000000000 XMR, idx 1/0
Height 949126, txid <0f5fcd710b94e49b61fedf93de92b444021292fbffb57c281ee6952190dc0bbf>, 1.110000000000 XMR, idx 1/1
Height 949126, txid <73a83e4de08d84d9d72c707c0406fcba92994a56feb42102e3ca7c3733613c5e>, 1.210000000000 XMR, idx 1/2
Height 949126, txid <9bdba78cd150cf4027282cdabb5893c0c7fb4c0d8ddf0f9096598b4bea87af69>, 1.230000000000 XMR, idx 1/2
Height 949126, txid <22e4ac8469654903da34ce06ab06840648338d9d9dfc3f59714777d7a5a5256b>, 1.120000000000 XMR, idx 1/1
Height 949126, txid <36b14c61ad93c4a8d16f10d88525222391717d87099bb30cd8c3da6c90849818>, 1.130000000000 XMR, idx 1/1
Height 949126, txid <99b7c48a24e44c3336dc0f4b884ad33e89668e4dd9c288c67e60ffea9506ed26>, 1.220000000000 XMR, idx 1/2
[wallet/0 9uPkEU]: account
        Account               Balance      Unlocked balance                 Label
       0 9uPkEU        1.080000000000        1.080000000000       My home account
       1 Bd2qqa       10.080000000000       10.080000000000 My secret business account
----------------------------------------------------------------------------------
          Total       11.160000000000       11.160000000000

The command balance shows the total balance of all the funds received by all the addresses belonging to the currently selected account. You can see the details about how much funds are received by which address by providing an optional argument detail:

[wallet/0 9uPkEU]: balance
Currently selected account: [0] My home account
Balance: 1.080000000000, unlocked balance: 1.080000000000

[wallet/0 9uPkEU]: balance detail
Currently selected account: [0] My home account
Balance: 1.080000000000, unlocked balance: 1.080000000000
Balance per address:
        Address               Balance      Unlocked balance                 Label Outputs
       0 9uPkEU        0.060000000000        0.060000000000       My home account       3
       1 BZ9PfX        0.360000000000        0.360000000000 ShapeShift purchase on 2017-Jul-08       3
       2 BfhF53        0.660000000000        0.660000000000 ShapeShift purchase on 2017-Jul-09       3

[wallet/0 9uPkEU]: account switch 1
Currently selected account: [1] My secret business account
Balance: 10.080000000000, unlocked balance: 10.080000000000

[wallet/1 Bd2qqa]: balance detail
Currently selected account: [1] My secret business account
Balance: 10.080000000000, unlocked balance: 10.080000000000
Balance per address:
        Address               Balance      Unlocked balance                 Label Outputs
       0 Bd2qqa        3.060000000000        3.060000000000 My secret business account       3
       1 BcGvNd        3.360000000000        3.360000000000                             3
       2 BgtuJh        3.660000000000        3.660000000000                             3

Other commands for showing detailed information about funds have some changes of syntax:

show_transfers [in|out|pending|failed|pool] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]]
incoming_transfers [available|unavailable] [index=<N1>[,<N2>,...]]
[wallet/1 Bd2qqa]: show_transfers index=0
  949116     in      03:34:43 AM       1.010000000000 92f3b54a3044eddf3fd84742852f8a81b55e92055281c945bd7dee85e589ccc2 0000000000000000 0 - 
  949117     in      03:35:30 AM       1.030000000000 d2617a1da91203247f8b904cf05906973cc9a64bff8d6ab4d956f22cb5d5271e 0000000000000000 0 - 
  949117     in      03:35:30 AM       1.020000000000 441b07d91f64adf1b4f8350ca33902ed4aab306df3f66e1673d35a151186140c 0000000000000000 0 - 

[wallet/1 Bd2qqa]: incoming_transfers index=1,2
               amount   spent    unlocked  ringct    global index                                                               tx id      addr index
       1.110000000000       F    unlocked  RingCT          219516  <0f5fcd710b94e49b61fedf93de92b444021292fbffb57c281ee6952190dc0bbf>               1
       1.210000000000       F    unlocked  RingCT          219518  <73a83e4de08d84d9d72c707c0406fcba92994a56feb42102e3ca7c3733613c5e>               2
       1.230000000000       F    unlocked  RingCT          219520  <9bdba78cd150cf4027282cdabb5893c0c7fb4c0d8ddf0f9096598b4bea87af69>               2
       1.120000000000       F    unlocked  RingCT          219522  <22e4ac8469654903da34ce06ab06840648338d9d9dfc3f59714777d7a5a5256b>               1
       1.130000000000       F    unlocked  RingCT          219524  <36b14c61ad93c4a8d16f10d88525222391717d87099bb30cd8c3da6c90849818>               1
       1.220000000000       F    unlocked  RingCT          219526  <99b7c48a24e44c3336dc0f4b884ad33e89668e4dd9c288c67e60ffea9506ed26>               2

3.5. Transferring funds

The apparently unrelated subaddresses might get statistically linked if funds transferred to different subaddresses are used together as inputs in new transactions. For example, suppose Bob published two subaddresses (C1,D1) and (C2,D2) in different places, and Alice repeatedly transferred funds to these addresses not knowing that they both belong to Bob. If Bob repeatedly used outputs received by these subaddresses together as inputs in new transactions, Alice would notice multiple instances of transactions where each of the input ring signatures contains the output she created for the payments to these subaddresses. The probability of such transactions occurring by chance would be fairly low, so she can confidently guess that these subaddresses belong to the same person.

To prevent this kind of potential risk of linkability, the wallet tries its best to avoid using outputs belonging to different subaddresses together as inputs in a new transaction. If there exist any subaddresses with enough unlocked balance for the requested transfer, the wallet chooses one randomly. If there is no such subaddress, the wallet uses the minimal number of subaddresses to cover the required amount while showing a warning message. You can also explicitly tell the wallet from which subaddresses the outputs should be picked by using an optional argument index=<N1>[,<N2>,...]:

transfer [index=<N1>[,<N2>,...]] [<priority>] [<mixin_count>] <address> <amount> [<payment_id>]
[wallet/1 Bd2qqa]: balance detail
Currently selected account: [1] My secret business account
Balance: 10.080000000000, unlocked balance: 10.080000000000
Balance per address:
        Address               Balance      Unlocked balance                 Label Outputs
       0 Bd2qqa        3.060000000000        3.060000000000 My secret business account       3
       1 BcGvNd        3.360000000000        3.360000000000                             3
       2 BgtuJh        3.660000000000        3.660000000000                             3

[wallet/1 Bd2qqa]: transfer 9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk 3  
Spending from address index 2
Sending 3.000000000000.  The transaction fee is 0.023390640000
Is this okay?  (Y/Yes/N/No): n
Error: transaction cancelled.

[wallet/1 Bd2qqa]: transfer 9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk 3
Spending from address index 1
Sending 3.000000000000.  The transaction fee is 0.023390640000
Is this okay?  (Y/Yes/N/No): n
Error: transaction cancelled.

[wallet/1 Bd2qqa]: transfer 9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk 3.2
Spending from address index 1
Sending 3.200000000000.  The transaction fee is 0.023390640000
Is this okay?  (Y/Yes/N/No): n
Error: transaction cancelled.

[wallet/1 Bd2qqa]: transfer 9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk 3.2
Spending from address index 2
Sending 3.200000000000.  The transaction fee is 0.023390640000
Is this okay?  (Y/Yes/N/No): n
Error: transaction cancelled.

[wallet/1 Bd2qqa]: transfer 9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk 3.5
Spending from address index 2
Sending 3.500000000000.  The transaction fee is 0.023390640000
Is this okay?  (Y/Yes/N/No): n
Error: transaction cancelled.

[wallet/1 Bd2qqa]: transfer 9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk 5
Spending from address index 1
Spending from address index 2
WARNING: Outputs of multiple addresses are being used together.
Sending 5.000000000000.  The transaction fee is 0.025061400000
Is this okay?  (Y/Yes/N/No): n
Error: transaction cancelled.

[wallet/1 Bd2qqa]: transfer index=0,1 9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk 5
Spending from address index 0
Spending from address index 1
WARNING: Outputs of multiple addresses are being used together.
Sending 5.000000000000.  The transaction fee is 0.025061400000
Is this okay?  (Y/Yes/N/No): n
Error: transaction cancelled.

[wallet/1 Bd2qqa]: transfer 9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk 9
Spending from address index 0
Spending from address index 1
Spending from address index 2
WARNING: Outputs of multiple addresses are being used together.
Sending 9.000000000000.  The transaction fee is 0.028402920000
Is this okay?  (Y/Yes/N/No): n
Error: transaction cancelled.

The command sweep_all has a similar syntax:

sweep_all [index=<N1>[,<N2>,...]] [<mixin_count>] <address> [<payment_id>]

If you omit the index parameter, one subaddress to be swept is chosen randomly (with index 0 being chosen last). You can use index=<N> to specify which subaddress to be swept. You can also either use index=<N1>,<N2>,... to sweep balances of multiple or all subaddresses.

[wallet/1 Bd2qqa]: sweep_all 9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk
Spending from address index 1
Sweeping 3.360000000000 for a total fee of 0.023390080000.  Is this okay?  (Y/Yes/N/No)n
Error: transaction cancelled.

[wallet/1 Bd2qqa]: sweep_all index=1,2 9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk
Spending from address index 1
Spending from address index 2
WARNING: Outputs of multiple addresses are being used together.
Sweeping 7.020000000000 for a total fee of 0.025060800000.  Is this okay?  (Y/Yes/N/No)n
Error: transaction cancelled.

Note that the change always goes to the base subaddress at index=0:

[wallet/1 Bd2qqa]: transfer 9svHk1wHPo3ULf2AZykghzcye6sitaRE4MaDjPC6uanTHCynHjJHZaiAb922PojE1GexhhRt1LVf5DC43feyrRZMLXQr3mk 1
Spending from address index 1
Sending 1.000000000000.  The transaction fee is 0.021719360000
Is this okay?  (Y/Yes/N/No): y
Money successfully sent, transaction <6f6678b4c6b3c60bcb7eb642bc819a1b99e9c75feb7c292b3656ea7b3b4f1a62>

Height 949248, txid <6f6678b4c6b3c60bcb7eb642bc819a1b99e9c75feb7c292b3656ea7b3b4f1a62>, 0.088280640000 XMR, idx 1/0
Height 949248, txid <6f6678b4c6b3c60bcb7eb642bc819a1b99e9c75feb7c292b3656ea7b3b4f1a62>, spent 1.110000000000, account 1

[wallet/1 Bd2qqa]: balance detail
Currently selected account: [1] My secret business account
Balance: 9.058280640000, unlocked balance: 8.970000000000
Balance per address:
        Address               Balance      Unlocked balance                 Label Outputs
       0 Bd2qqa        3.148280640000        3.060000000000 My secret business account       4
       1 BcGvNd        2.250000000000        2.250000000000                             2
       2 BgtuJh        3.660000000000        3.660000000000                             3

3.6. Restoring wallet from seed

One slight caveat with this scheme is that when restoring a wallet from the seed, the wallet might miss transfers to subaddresses if they aren't stored in the hashtable yet. To mitigate this issue, for each account, the wallet stores 200 (a constant SUBADDRESS_LOOKAHEAD_MINOR defined in wallet2.h) subaddresses of indices beyond the highest index created so far. The wallet also generates 50 (a constant SUBADDRESS_LOOKAHEAD_MAJOR defined in wallet2.h) accounts beyond the highest index created so far. This means that the wallet restoration process is guaranteed to find incoming transfers to subaddresses as long as the major and minor indices of the used subaddresses differ by less than those predefined numbers. Note that the wallet expands the hashtable by itself as it finds incoming transfers to subaddresses at new higher indices, so normally the user won't need to worry about the management of the hashtable. Even if the differences of indices are bigger than those predifined numbers, you can still make the wallet recognize the incoming transfers by manually expanding the hashtable and rescanning the blockchain.

Here's an example: First, we generate 360 new addresses for the 1st account:

[wallet/1 Bd2qqa]: address all
0  Bd2qqam2EKc8NRzTYg9QPJZ81Ey1WRp1Bcnmjzf28K3edRyr1rcLbjiQZdR7tsuTUJBahi32RSDb1cuqsACaEDwGRMZ4Eaa  My secret business account (used)
1  BcGvNdmZj9V9r7NKAKzEELUVVSVfXMmUUbfQrjSBuDt6MU5bdtmYAEC6TR5VuZQv5yZvynzQ3aoJTUjtM9FD5AnP9PCHVSk   (used)
2  BgtuJhWFPi9DABnpdtQs9rWfQN33DZQZi2yzoQucEAP8EoPxNDitssoA14ZVQthSyPHWB8SLV48qAc25A1EykehQ7NzDXDb   (used)
3  BYfn1Fc5xwECX2HbNATqfuQCG82sMZufY46ZsiP1xBbR3S6fVj2P4d4MLRrqVBZcFHUQmdiCsKa3ec5aaNVk35ZYHQnLbu1  
...
150  BgjoPu6qBNVT1E9c3PDaaw9zbehhG29vBQAH8mSeC79K7z2qb12ZtTH1ijo4Tn7DYQPm2aZq68yrnLcoi18baf9JQxmn2bZ  
...
360  BZ1xAbycuHyKwangpgEn7NTWk2geNbcJgJ46iCkRBu8Gc2UXTACeRcUGWneGA1mPfkKmpy7ya4ST9dZex3RN2qi5BLdQRxy  

Next, we generate 70 accounts and print the base addresses of the 15th and 70th accounts:

[wallet/70 BbXfcf]: account
        Account               Balance      Unlocked balance                 Label
       0 9uPkEU        1.080000000000        1.080000000000       My home account
       1 Bd2qqa        9.058280640000        9.058280640000 My secret business account
       2 BaTkbd        0.000000000000        0.000000000000                      
       3 BeaUVm        0.000000000000        0.000000000000                      
...
      70 BbXfcf        0.000000000000        0.000000000000                      
----------------------------------------------------------------------------------
          Total       10.138280640000       10.138280640000

[wallet/0 9uPkEU]: account switch 15
Currently selected account: [15] 
Balance: 0.000000000000, unlocked balance: 0.000000000000

[wallet/15 BhQjPZ]: address
0  BhQjPZ8XUkojSdcB8jhB4uTeqLQVHtfsYTxTm3n32yXM37qXqN8RdTXduKSEH4rrAp4ZuUFbv8Wak3i1QudCJhvwJVUU5dx  

[wallet/15 BhQjPZ]: account switch 70
Currently selected account: [70] 
Balance: 0.000000000000, unlocked balance: 0.000000000000

[wallet/70 BbXfcf]: address
0  BbXfcfWRiUAcG7hoXvdRY8QtVisRPj1EQEbMoWWHGPXqQKVKWoSNNgbPEuSFm6YuDHUVaWwyqu876WKZrUmVMk8DLsrSMSN  

Then we send funds to these addresses (at indices of 1/150, 1/360, 15/0, 70/0) from another wallet:

[wallet/0 9svHk1]: transfer BgjoPu6qBNVT1E9c3PDaaw9zbehhG29vBQAH8mSeC79K7z2qb12ZtTH1ijo4Tn7DYQPm2aZq68yrnLcoi18baf9JQxmn2bZ 1  
Money successfully sent, transaction <ddb1d29f54f4de8e88fddd31379d6bf30ba4d311ae648d05c9962cfb59e494b1>

[wallet/0 9svHk1]: transfer BZ1xAbycuHyKwangpgEn7NTWk2geNbcJgJ46iCkRBu8Gc2UXTACeRcUGWneGA1mPfkKmpy7ya4ST9dZex3RN2qi5BLdQRxy 2
Money successfully sent, transaction <c4292519b328fcfa8f92300d55a33a1d9a2b1788b0988c501adea6a51452f52a>

[wallet/0 9svHk1]: transfer BhQjPZ8XUkojSdcB8jhB4uTeqLQVHtfsYTxTm3n32yXM37qXqN8RdTXduKSEH4rrAp4ZuUFbv8Wak3i1QudCJhvwJVUU5dx 3
Money successfully sent, transaction <8c473e823e6b1262a55b8456c19f1b9fba0090c089222435c3bccdbeac10fc99>

[wallet/0 9svHk1]: transfer BbXfcfWRiUAcG7hoXvdRY8QtVisRPj1EQEbMoWWHGPXqQKVKWoSNNgbPEuSFm6YuDHUVaWwyqu876WKZrUmVMk8DLsrSMSN 4
Money successfully sent, transaction <27d55c3af091cccb9e9fc6eb17f0e3e6ff700af066fb6471a3533c4f19af70c3>

Now we delete the cache of the receiving wallet 9uPkEU and re-generate it by scanning the blockchain again (which gives the same effect as restoring the wallet from the seed):

Monero 'Wolfram Warptangent' (v0.10.3.1-a261d3b)
Logging to /Users/kenshi/dev/github/kenshi84/monero/build/release/bin/monero-wallet-cli.log
Wallet password: *
Opened wallet: 9uPkEUFcFujaw1YCDHhcvuUqQm9cGBBuu5KkGggFR9XMjQtXtFzUDbRU9oy4XYer9SeaSGAhtoT1xDsBuVDRqfg9GG2ji9U
**********************************************************************
Use "help" command to see the list of available commands.
**********************************************************************
Starting refresh...
Height 949115, txid <2c9d55d65f67243f771729ecd93a089ca0fcde3451f5a7740a4df70d8240b95b>, 0.130000000000 XMR, idx 0/1
Height 949115, txid <68ee8848bbb953e3a0bc8d3175e8724c3fb04cd2e49244c76d26d5b2fa2a6da2>, 0.020000000000 XMR, idx 0/0
Height 949115, txid <01f3865e63613413f6de4d4cd2b2638b679aa604c06299ad4b562364afc8cf5a>, 0.110000000000 XMR, idx 0/1
Height 949115, txid <b3bd13988448ef3bb95e6f3bf007f42ebc4f0d21346b6c4d45e42d53caa3e297>, 0.120000000000 XMR, idx 0/1
Height 949115, txid <05a97709858358ec8bb008cc8ad7f70e35ec07219cc8744138473200bb9922ec>, 0.230000000000 XMR, idx 0/2
Height 949115, txid <9a1527acdce60bbe38c8c7e9d3bfe894108d5b30eb630904a3b3afd5059b3344>, 0.210000000000 XMR, idx 0/2
Height 949115, txid <6716c0707b4c198777adbcda6b630b6248ef07fb86d20ba4469dcf661f5b35ee>, 0.010000000000 XMR, idx 0/0
Height 949115, txid <04bf1d9a5b8b3fe74d26bd068844f4709b22c92f6a3b5594f217c22df88f8184>, 0.030000000000 XMR, idx 0/0
Height 949115, txid <02b76b48467a806c6e45ce6fdf59df3c694f857f450a450537a9769f911fee46>, 0.220000000000 XMR, idx 0/2
Height 949116, txid <92f3b54a3044eddf3fd84742852f8a81b55e92055281c945bd7dee85e589ccc2>, 1.010000000000 XMR, idx 1/0
Height 949117, txid <d2617a1da91203247f8b904cf05906973cc9a64bff8d6ab4d956f22cb5d5271e>, 1.030000000000 XMR, idx 1/0
Height 949117, txid <441b07d91f64adf1b4f8350ca33902ed4aab306df3f66e1673d35a151186140c>, 1.020000000000 XMR, idx 1/0
Height 949126, txid <0f5fcd710b94e49b61fedf93de92b444021292fbffb57c281ee6952190dc0bbf>, 1.110000000000 XMR, idx 1/1
Height 949126, txid <73a83e4de08d84d9d72c707c0406fcba92994a56feb42102e3ca7c3733613c5e>, 1.210000000000 XMR, idx 1/2
Height 949126, txid <9bdba78cd150cf4027282cdabb5893c0c7fb4c0d8ddf0f9096598b4bea87af69>, 1.230000000000 XMR, idx 1/2
Height 949126, txid <22e4ac8469654903da34ce06ab06840648338d9d9dfc3f59714777d7a5a5256b>, 1.120000000000 XMR, idx 1/1
Height 949126, txid <36b14c61ad93c4a8d16f10d88525222391717d87099bb30cd8c3da6c90849818>, 1.130000000000 XMR, idx 1/1
Height 949126, txid <99b7c48a24e44c3336dc0f4b884ad33e89668e4dd9c288c67e60ffea9506ed26>, 1.220000000000 XMR, idx 1/2
Height 949248, txid <6f6678b4c6b3c60bcb7eb642bc819a1b99e9c75feb7c292b3656ea7b3b4f1a62>, 0.088280640000 XMR, idx 1/0
Height 949248, txid <6f6678b4c6b3c60bcb7eb642bc819a1b99e9c75feb7c292b3656ea7b3b4f1a62>, spent 1.110000000000, account 1
Height 949344, txid <ddb1d29f54f4de8e88fddd31379d6bf30ba4d311ae648d05c9962cfb59e494b1>, 1.000000000000 XMR, idx 1/150
Height 949344, txid <8c473e823e6b1262a55b8456c19f1b9fba0090c089222435c3bccdbeac10fc99>, 3.000000000000 XMR, idx 15/0
Refresh done, blocks received: 24696                            
        Account               Balance      Unlocked balance                 Label
       0 9uPkEU        1.080000000000        1.080000000000               Default
       1 Bd2qqa       10.058280640000        9.058280640000                      
       2 BaTkbd        0.000000000000        0.000000000000                      
       3 BeaUVm        0.000000000000        0.000000000000                      
       4 BfH7tK        0.000000000000        0.000000000000                      
       5 BfDmWH        0.000000000000        0.000000000000                      
       6 BfwsE7        0.000000000000        0.000000000000                      
       7 Bam7fW        0.000000000000        0.000000000000                      
       8 BePNm3        0.000000000000        0.000000000000                      
       9 BgkPAD        0.000000000000        0.000000000000                      
      10 BYQtBx        0.000000000000        0.000000000000                      
      11 BZEjtF        0.000000000000        0.000000000000                      
      12 BbkUr7        0.000000000000        0.000000000000                      
      13 Bg34Jy        0.000000000000        0.000000000000                      
      14 BYqzux        0.000000000000        0.000000000000                      
      15 BhQjPZ        3.000000000000        0.000000000000                      
----------------------------------------------------------------------------------
          Total       14.138280640000       10.138280640000
Currently selected account: [0] Default
Balance: 1.080000000000, unlocked balance: 1.080000000000
Background refresh thread started

Note that at this point, the wallet was able to successfully recognize incoming transfers to indices of 1/150 and 15/0, but failed to recognize incoming transfers to 1/360 and 70/0 because 360 > 150 + SUBADDRESS_LOOKAHEAD_MINOR and 70 > 15 + SUBADDRESS_LOOKAHEAD_MAJOR. You can make the wallet recognize those incoming transfers by manually expanding the hashtable and rescanning the blockchain:

[wallet/1 Bd2qqa]: address new
151  BaTjSeUuSX4KtS6DmQXRfcN3xkTAyuG2NMg3r6JpR4JujotNw8dvGKBbVehURSoMSpSsKJQTWi4eQCJxsjXuXber9WUKQ53  

...

[wallet/1 Bd2qqa]: address new
161  BbA5zmZzn9ZPvzazMHBjQzXZHaYDjWeWfN258AZufhPK3i2uF6GCdvGMMksA7qMmXxcswEfkwucuuJPDYGvR77Ux7iczJzD  

[wallet/1 Bd2qqa]: account new
        Account               Balance      Unlocked balance                 Label
       0 9uPkEU        1.080000000000        1.080000000000               Default
       1 Bd2qqa       10.058280640000        9.058280640000                      
       2 BaTkbd        0.000000000000        0.000000000000                      
       3 BeaUVm        0.000000000000        0.000000000000                      
       4 BfH7tK        0.000000000000        0.000000000000                      
       5 BfDmWH        0.000000000000        0.000000000000                      
       6 BfwsE7        0.000000000000        0.000000000000                      
       7 Bam7fW        0.000000000000        0.000000000000                      
       8 BePNm3        0.000000000000        0.000000000000                      
       9 BgkPAD        0.000000000000        0.000000000000                      
      10 BYQtBx        0.000000000000        0.000000000000                      
      11 BZEjtF        0.000000000000        0.000000000000                      
      12 BbkUr7        0.000000000000        0.000000000000                      
      13 Bg34Jy        0.000000000000        0.000000000000                      
      14 BYqzux        0.000000000000        0.000000000000                      
      15 BhQjPZ        3.000000000000        0.000000000000                      
      16 BePZ3e        0.000000000000        0.000000000000                      
----------------------------------------------------------------------------------
          Total       14.138280640000       10.138280640000

...

[wallet/20 BgjB9f]: account new
        Account               Balance      Unlocked balance                 Label
       0 9uPkEU        1.080000000000        1.080000000000               Default
       1 Bd2qqa       12.058280640000        9.058280640000                      
       2 BaTkbd        0.000000000000        0.000000000000                      
       3 BeaUVm        0.000000000000        0.000000000000                      
       4 BfH7tK        0.000000000000        0.000000000000                      
       5 BfDmWH        0.000000000000        0.000000000000                      
       6 BfwsE7        0.000000000000        0.000000000000                      
       7 Bam7fW        0.000000000000        0.000000000000                      
       8 BePNm3        0.000000000000        0.000000000000                      
       9 BgkPAD        0.000000000000        0.000000000000                      
      10 BYQtBx        0.000000000000        0.000000000000                      
      11 BZEjtF        0.000000000000        0.000000000000                      
      12 BbkUr7        0.000000000000        0.000000000000                      
      13 Bg34Jy        0.000000000000        0.000000000000                      
      14 BYqzux        0.000000000000        0.000000000000                      
      15 BhQjPZ        3.000000000000        0.000000000000                      
      16 BePZ3e        0.000000000000        0.000000000000                      
      17 BcMMgP        0.000000000000        0.000000000000                      
      18 Bf7N2v        0.000000000000        0.000000000000                      
      19 BbNHEQ        0.000000000000        0.000000000000                      
      20 BgjB9f        0.000000000000        0.000000000000                      
      21 Bd1dhR        0.000000000000        0.000000000000                      
----------------------------------------------------------------------------------
          Total       16.138280640000       10.138280640000


[wallet/21 Bd1dhR]: rescan_bc
Starting refresh...
Height 949115, txid <2c9d55d65f67243f771729ecd93a089ca0fcde3451f5a7740a4df70d8240b95b>, 0.130000000000 XMR, idx 0/1
Height 949115, txid <68ee8848bbb953e3a0bc8d3175e8724c3fb04cd2e49244c76d26d5b2fa2a6da2>, 0.020000000000 XMR, idx 0/0
Height 949115, txid <01f3865e63613413f6de4d4cd2b2638b679aa604c06299ad4b562364afc8cf5a>, 0.110000000000 XMR, idx 0/1
Height 949115, txid <b3bd13988448ef3bb95e6f3bf007f42ebc4f0d21346b6c4d45e42d53caa3e297>, 0.120000000000 XMR, idx 0/1
Height 949115, txid <05a97709858358ec8bb008cc8ad7f70e35ec07219cc8744138473200bb9922ec>, 0.230000000000 XMR, idx 0/2
Height 949115, txid <9a1527acdce60bbe38c8c7e9d3bfe894108d5b30eb630904a3b3afd5059b3344>, 0.210000000000 XMR, idx 0/2
Height 949115, txid <6716c0707b4c198777adbcda6b630b6248ef07fb86d20ba4469dcf661f5b35ee>, 0.010000000000 XMR, idx 0/0
Height 949115, txid <04bf1d9a5b8b3fe74d26bd068844f4709b22c92f6a3b5594f217c22df88f8184>, 0.030000000000 XMR, idx 0/0
Height 949115, txid <02b76b48467a806c6e45ce6fdf59df3c694f857f450a450537a9769f911fee46>, 0.220000000000 XMR, idx 0/2
Height 949116, txid <92f3b54a3044eddf3fd84742852f8a81b55e92055281c945bd7dee85e589ccc2>, 1.010000000000 XMR, idx 1/0
Height 949117, txid <d2617a1da91203247f8b904cf05906973cc9a64bff8d6ab4d956f22cb5d5271e>, 1.030000000000 XMR, idx 1/0
Height 949117, txid <441b07d91f64adf1b4f8350ca33902ed4aab306df3f66e1673d35a151186140c>, 1.020000000000 XMR, idx 1/0
Height 949126, txid <0f5fcd710b94e49b61fedf93de92b444021292fbffb57c281ee6952190dc0bbf>, 1.110000000000 XMR, idx 1/1
Height 949126, txid <73a83e4de08d84d9d72c707c0406fcba92994a56feb42102e3ca7c3733613c5e>, 1.210000000000 XMR, idx 1/2
Height 949126, txid <9bdba78cd150cf4027282cdabb5893c0c7fb4c0d8ddf0f9096598b4bea87af69>, 1.230000000000 XMR, idx 1/2
Height 949126, txid <22e4ac8469654903da34ce06ab06840648338d9d9dfc3f59714777d7a5a5256b>, 1.120000000000 XMR, idx 1/1
Height 949126, txid <36b14c61ad93c4a8d16f10d88525222391717d87099bb30cd8c3da6c90849818>, 1.130000000000 XMR, idx 1/1
Height 949126, txid <99b7c48a24e44c3336dc0f4b884ad33e89668e4dd9c288c67e60ffea9506ed26>, 1.220000000000 XMR, idx 1/2
Height 949248, txid <6f6678b4c6b3c60bcb7eb642bc819a1b99e9c75feb7c292b3656ea7b3b4f1a62>, 0.088280640000 XMR, idx 1/0
Height 949248, txid <6f6678b4c6b3c60bcb7eb642bc819a1b99e9c75feb7c292b3656ea7b3b4f1a62>, spent 1.110000000000, account 1
Height 949344, txid <c4292519b328fcfa8f92300d55a33a1d9a2b1788b0988c501adea6a51452f52a>, 2.000000000000 XMR, idx 1/360
Height 949344, txid <ddb1d29f54f4de8e88fddd31379d6bf30ba4d311ae648d05c9962cfb59e494b1>, 1.000000000000 XMR, idx 1/150
Height 949344, txid <27d55c3af091cccb9e9fc6eb17f0e3e6ff700af066fb6471a3533c4f19af70c3>, 4.000000000000 XMR, idx 70/0
Height 949344, txid <8c473e823e6b1262a55b8456c19f1b9fba0090c089222435c3bccdbeac10fc99>, 3.000000000000 XMR, idx 15/0
Refresh done, blocks received: 24699                            
Currently selected account: [21] 
Balance: 0.000000000000, unlocked balance: 0.000000000000

4. ToDo

  • Review
  • Unit test & performance test
  • Update MRL-0006

5. Related links

Acknowledgements

  • @JollyMort for initial discussions since the very beginning
  • @knaccc for bringing up the concept of sub-addresses with a modified DH key exchange idea, and also for pointing out the fact that the change can be sent to any subaddresses
  • @RandomRun for the second generation modified DH key exchange idea that solves the problem of discovery of the main wallet keys
  • @luigi1111 for various suggestions and guidance
@NanoAkron

This comment has been minimized.

Show comment
Hide comment
@NanoAkron

NanoAkron May 30, 2017

Contributor

Is there a possibility of sweeping all subaddress funds back into my main address? Is that how bitcoin's HD wallet works? Or would that be more like the 'disposable address' scheme...?

Contributor

NanoAkron commented May 30, 2017

Is there a possibility of sweeping all subaddress funds back into my main address? Is that how bitcoin's HD wallet works? Or would that be more like the 'disposable address' scheme...?

@JollyMort

This comment has been minimized.

Show comment
Hide comment
@JollyMort

JollyMort May 30, 2017

Contributor

Remember, funds never reside on some address. Fundamentally, all the outputs belong to you because you can recover the individual outputs' private keys and they're not associated with an address. If the sender lost the relevant TX key, nobody can ever prove an output was sent to some address unless you give them the view key. Even if you know from your records you sent x monero to address y in TX z, you can't ever prove it without TX key or view key. If the sender sent to your sub A, and you spend it together with something from sub B, he can't tell that's from a different address because they're never linked to an address (unless he was the one who sent to B, in which case he'd have the TX key in local records). He can't even tell you're spending at all since you're using a ring signature :)

So, grouping them into addresses or sub-addresses is kind of arbitrary.
But yeah, it could be useful to draw borders and avoid combining some together, and have the sweep_all to collect from all subs (does it do that already?)

Contributor

JollyMort commented May 30, 2017

Remember, funds never reside on some address. Fundamentally, all the outputs belong to you because you can recover the individual outputs' private keys and they're not associated with an address. If the sender lost the relevant TX key, nobody can ever prove an output was sent to some address unless you give them the view key. Even if you know from your records you sent x monero to address y in TX z, you can't ever prove it without TX key or view key. If the sender sent to your sub A, and you spend it together with something from sub B, he can't tell that's from a different address because they're never linked to an address (unless he was the one who sent to B, in which case he'd have the TX key in local records). He can't even tell you're spending at all since you're using a ring signature :)

So, grouping them into addresses or sub-addresses is kind of arbitrary.
But yeah, it could be useful to draw borders and avoid combining some together, and have the sweep_all to collect from all subs (does it do that already?)

@xmrgit

This comment has been minimized.

Show comment
Hide comment
@xmrgit

xmrgit May 30, 2017

just registered to ask if we can have a sweep_all for every sub-address instead of just move_sub2main

so more something like sweep_all_sub 2 0 which will move all funds from sub-address 2 to sub-address 0
and sweep_all_sub 2 2 will move all funds from sub-address 2 to sub-address 2 to create just 1 input.

I like to sweep my current sub-wallets usually more than 1 time before I send them to my main-wallet(s) for privacy reasons.

otherwise great pr, will save me some time to create and backup a new wallet every time.

xmrgit commented May 30, 2017

just registered to ask if we can have a sweep_all for every sub-address instead of just move_sub2main

so more something like sweep_all_sub 2 0 which will move all funds from sub-address 2 to sub-address 0
and sweep_all_sub 2 2 will move all funds from sub-address 2 to sub-address 2 to create just 1 input.

I like to sweep my current sub-wallets usually more than 1 time before I send them to my main-wallet(s) for privacy reasons.

otherwise great pr, will save me some time to create and backup a new wallet every time.

@knaccc

This comment has been minimized.

Show comment
Hide comment
@knaccc

knaccc May 30, 2017

I second @xmrgit 's suggestion. Fantastic stuff, @kenshi84, very elegant.

knaccc commented May 30, 2017

I second @xmrgit 's suggestion. Fantastic stuff, @kenshi84, very elegant.

@Jaqueeee

This comment has been minimized.

Show comment
Hide comment
@Jaqueeee

Jaqueeee May 31, 2017

Contributor

Good work! What's the impact on performance when rescanning blockchain? Has it been benchmarked?

Contributor

Jaqueeee commented May 31, 2017

Good work! What's the impact on performance when rescanning blockchain? Has it been benchmarked?

@dan-da

This comment has been minimized.

Show comment
Hide comment
@dan-da

dan-da Jun 1, 2017

Error: No outputs found, or daemon is not ready

Can this error message be improved? Even as a technical user, this would mislead me.

Perhaps something like: "Error: No single sub-address contains adequate funds although wallet balance is sufficient. Suggestion: aggregate funds to a fresh address."

dan-da commented Jun 1, 2017

Error: No outputs found, or daemon is not ready

Can this error message be improved? Even as a technical user, this would mislead me.

Perhaps something like: "Error: No single sub-address contains adequate funds although wallet balance is sufficient. Suggestion: aggregate funds to a fresh address."

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Jun 3, 2017

Contributor

Thank you guys for your feedback!

@xmrgit @knaccc
I agree with your point, so I dropped the command move_sub2main now and instead modified the command sweep_all such that it optionally accepts the index of subaddress to be swept. Please check the updated OP above, I hope it achieves what you had in mind.

@NanoAkron

Is there a possibility of sweeping all subaddress funds back into my main address?

Yes, it's possible to sweep all the balance of each subaddress to the main address individually. Alternatively, although not recommended for privacy reasons, it's also possible to sweep all the balances of all the subaddresses to the main address in a single transaction if you switch off the safeguard by doing set allow-combine-subaddresses 1.

Is that how bitcoin's HD wallet works?

Conceptually it's kind of similar to Bitcoin's HD wallet, but the actual problem being addressed here is vastly different because in Monero, wallet addresses never appear in the blockchain as @JollyMort stressed.

Or would that be more like the 'disposable address' scheme...?

I couldn't understand your question...

@JollyMort

unless he was the one who sent to B

This is the concern addressed by the "not combining subaddresses" scheme. If Alice sent some funds to two different subaddresses and saw a transaction later that included those two outputs in the input ring signatures, she would guess that the two subaddresses belong to the same person.

it could be useful to draw borders and avoid combining some together, and have the sweep_all to collect from all subs (does it do that already?)

It's not recommended (but still possible) to sweep all the funds in all the subaddresses to the main address at once, due to the above reason.

@Jaqueeee

What's the impact on performance when rescanning blockchain? Has it been benchmarked?

No, it's not benchmarked yet. But my guess is that the additional cost for blockchain scanning will be really small (i.e. 1 hashtable lookup, 1 hash computation, and 1 scalar addition, for each incoming tranfer).

@dan-da

Thanks a lot for your suggestion! I changed the error message following your suggestion, please see the updated OP.

Contributor

kenshi84 commented Jun 3, 2017

Thank you guys for your feedback!

@xmrgit @knaccc
I agree with your point, so I dropped the command move_sub2main now and instead modified the command sweep_all such that it optionally accepts the index of subaddress to be swept. Please check the updated OP above, I hope it achieves what you had in mind.

@NanoAkron

Is there a possibility of sweeping all subaddress funds back into my main address?

Yes, it's possible to sweep all the balance of each subaddress to the main address individually. Alternatively, although not recommended for privacy reasons, it's also possible to sweep all the balances of all the subaddresses to the main address in a single transaction if you switch off the safeguard by doing set allow-combine-subaddresses 1.

Is that how bitcoin's HD wallet works?

Conceptually it's kind of similar to Bitcoin's HD wallet, but the actual problem being addressed here is vastly different because in Monero, wallet addresses never appear in the blockchain as @JollyMort stressed.

Or would that be more like the 'disposable address' scheme...?

I couldn't understand your question...

@JollyMort

unless he was the one who sent to B

This is the concern addressed by the "not combining subaddresses" scheme. If Alice sent some funds to two different subaddresses and saw a transaction later that included those two outputs in the input ring signatures, she would guess that the two subaddresses belong to the same person.

it could be useful to draw borders and avoid combining some together, and have the sweep_all to collect from all subs (does it do that already?)

It's not recommended (but still possible) to sweep all the funds in all the subaddresses to the main address at once, due to the above reason.

@Jaqueeee

What's the impact on performance when rescanning blockchain? Has it been benchmarked?

No, it's not benchmarked yet. But my guess is that the additional cost for blockchain scanning will be really small (i.e. 1 hashtable lookup, 1 hash computation, and 1 scalar addition, for each incoming tranfer).

@dan-da

Thanks a lot for your suggestion! I changed the error message following your suggestion, please see the updated OP.

@JollyMort

This comment has been minimized.

Show comment
Hide comment
@JollyMort

JollyMort Jun 3, 2017

Contributor

This is the concern addressed by the "not combining subaddresses" scheme. If Alice sent some funds to two different subaddresses and saw a transaction later that included those two outputs in the input ring signatures, she would guess that the two subaddresses belong to the same person.

Yup. But I could by chance make a ring signature using some 2 inputs to which Alice sent funds (to someone else, not me) in my ring and she could come to the same (but wrong) conclusion :) Plausible deniability FTW

Contributor

JollyMort commented Jun 3, 2017

This is the concern addressed by the "not combining subaddresses" scheme. If Alice sent some funds to two different subaddresses and saw a transaction later that included those two outputs in the input ring signatures, she would guess that the two subaddresses belong to the same person.

Yup. But I could by chance make a ring signature using some 2 inputs to which Alice sent funds (to someone else, not me) in my ring and she could come to the same (but wrong) conclusion :) Plausible deniability FTW

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Jun 3, 2017

Contributor

Yup. But I could by chance make a ring signature using some 2 inputs to which Alice sent funds (to someone else, not me) in my ring and she could come to the same (but wrong) conclusion :) Plausible deniability FTW

The point is that the likelihood of such an event is fairly low considering the enormous number of outputs in the blockchain, and if this happens repeatedly, the plausible deniability starts to diminish pretty quickly.

Contributor

kenshi84 commented Jun 3, 2017

Yup. But I could by chance make a ring signature using some 2 inputs to which Alice sent funds (to someone else, not me) in my ring and she could come to the same (but wrong) conclusion :) Plausible deniability FTW

The point is that the likelihood of such an event is fairly low considering the enormous number of outputs in the blockchain, and if this happens repeatedly, the plausible deniability starts to diminish pretty quickly.

@xmrgit

This comment has been minimized.

Show comment
Hide comment
@xmrgit

xmrgit Jun 4, 2017

would it also make sense to modify the command transfer such that it optionally accepts the index of a subaddress instead of only be able to randomly choosing a subaddress to be spent?

xmrgit commented Jun 4, 2017

would it also make sense to modify the command transfer such that it optionally accepts the index of a subaddress instead of only be able to randomly choosing a subaddress to be spent?

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Jun 8, 2017

Contributor

@xmrgit @knaccc
The CLI has been updated quite a bit, please check the edited OP (after section 3).

Contributor

kenshi84 commented Jun 8, 2017

@xmrgit @knaccc
The CLI has been updated quite a bit, please check the edited OP (after section 3).

@knaccc

This comment has been minimized.

Show comment
Hide comment
@knaccc

knaccc Jun 8, 2017

Minor note: I think it might help if the command syntax:
address [ <index_min> [<index_max>]|fresh ]
was instead written as:
address [ [<index_min> [<index_max>]] | fresh ]

knaccc commented Jun 8, 2017

Minor note: I think it might help if the command syntax:
address [ <index_min> [<index_max>]|fresh ]
was instead written as:
address [ [<index_min> [<index_max>]] | fresh ]

@knaccc

This comment has been minimized.

Show comment
Hide comment
@knaccc

knaccc Jun 8, 2017

I'm a little concerned that the wallet implementation you've proposed could diverge enormously from the GUI implementation, and lead to confusion.

If the GUI were to present just a single wallet to users with a main balance and then a list of subaddresses, then that would match perfectly with what you've implemented.

However, if the GUI presents the user with the ability to create different subwallets each with their own main balance, and with the abilitiy to create additional aliases per subwallet, then the terminology and UI will be completely different between the GUI and CLI.

Therefore I think that before proceeding, it needs to be decided whether the GUI will actually provide users with just subaddresses, or instead subwallets and aliases.

knaccc commented Jun 8, 2017

I'm a little concerned that the wallet implementation you've proposed could diverge enormously from the GUI implementation, and lead to confusion.

If the GUI were to present just a single wallet to users with a main balance and then a list of subaddresses, then that would match perfectly with what you've implemented.

However, if the GUI presents the user with the ability to create different subwallets each with their own main balance, and with the abilitiy to create additional aliases per subwallet, then the terminology and UI will be completely different between the GUI and CLI.

Therefore I think that before proceeding, it needs to be decided whether the GUI will actually provide users with just subaddresses, or instead subwallets and aliases.

@xmrgit

This comment has been minimized.

Show comment
Hide comment
@xmrgit

xmrgit Jun 8, 2017

@kenshi84
I love your work.

does it make sense to have the <index=n> in sweep_all as currently optional instead of required?

and would it make sense if <index=n> can have more than one n as input? so something like this index=1,2,5,10050?

xmrgit commented Jun 8, 2017

@kenshi84
I love your work.

does it make sense to have the <index=n> in sweep_all as currently optional instead of required?

and would it make sense if <index=n> can have more than one n as input? so something like this index=1,2,5,10050?

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Jun 10, 2017

Contributor

@knaccc
I see your point, and I'm aware that this PR needs to go hand in hand with the rest of the software ecosystem including GUI & RPC & probably also MyMonero etc.

However, if the GUI presents the user with the ability to create different subwallets each with their own main balance, and with the abilitiy to create additional aliases per subwallet, then the terminology and UI will be completely different between the GUI and CLI.

I'm still unsure about the meaning of those terms: Is an "alias" something different from a subaddress? Is a "subwallet" something like a full wallet whose seed is deterministically generated by some "master" seed? I haven't seen any detailed discussion on their exact definitions and merits.

There seems to be a general interest in managing different wallet files, either for the purpose of not revealing your identity through address reuse (which is addressed by this PR) or for the protection against KYC/AML demanding your viewkey (which isn't addressed by this PR).

monero-project/monero-gui#394

To me, opening different wallet files in GUI each having subtotal balances for their subaddresses doesn't seem too complicated or confusing, as long as we get the terminology right.

@xmrgit
Thanks a lot for your suggestion! I updated the syntax for transfer and sweep_all as you suggested, please see section 3.4.

does it make sense to have the <index=n> in sweep_all as currently optional instead of required?

The index parameter is already optional in both transfer and sweep_all.

Contributor

kenshi84 commented Jun 10, 2017

@knaccc
I see your point, and I'm aware that this PR needs to go hand in hand with the rest of the software ecosystem including GUI & RPC & probably also MyMonero etc.

However, if the GUI presents the user with the ability to create different subwallets each with their own main balance, and with the abilitiy to create additional aliases per subwallet, then the terminology and UI will be completely different between the GUI and CLI.

I'm still unsure about the meaning of those terms: Is an "alias" something different from a subaddress? Is a "subwallet" something like a full wallet whose seed is deterministically generated by some "master" seed? I haven't seen any detailed discussion on their exact definitions and merits.

There seems to be a general interest in managing different wallet files, either for the purpose of not revealing your identity through address reuse (which is addressed by this PR) or for the protection against KYC/AML demanding your viewkey (which isn't addressed by this PR).

monero-project/monero-gui#394

To me, opening different wallet files in GUI each having subtotal balances for their subaddresses doesn't seem too complicated or confusing, as long as we get the terminology right.

@xmrgit
Thanks a lot for your suggestion! I updated the syntax for transfer and sweep_all as you suggested, please see section 3.4.

does it make sense to have the <index=n> in sweep_all as currently optional instead of required?

The index parameter is already optional in both transfer and sweep_all.

@xmrgit

This comment has been minimized.

Show comment
Hide comment
@xmrgit

xmrgit Jun 10, 2017

@kenshi84

The index parameter is already optional in both transfer and sweep_all.

I mean, that I don't know any example where sweep_all needs index parameter as optional, because you usually know exactly which amount/sub-address you like to sweep. that's why I would change index in sweep_all to required. but maybe there are good examples where a random sub-address selection in sweep_all command makes sense?

Sorry for my bad english.

xmrgit commented Jun 10, 2017

@kenshi84

The index parameter is already optional in both transfer and sweep_all.

I mean, that I don't know any example where sweep_all needs index parameter as optional, because you usually know exactly which amount/sub-address you like to sweep. that's why I would change index in sweep_all to required. but maybe there are good examples where a random sub-address selection in sweep_all command makes sense?

Sorry for my bad english.

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Jun 10, 2017

Contributor

@xmrgit
Oh, I took your comment the opposite way. My intention of having the index parameter as optional is to allow the user to easily move funds from subaddresses to your main address by simply repeating

sweep_all <your main address>

until there's no subaddress with unlocked balance.

In general, I designed the CLI such that funds in subaddresses tend to accumulate in the main address (by randomly choosing non-zero index first before index=0), because all the change outputs go to the main address, regardless of whether the destination is a standard address or a subaddress. In other words, my intention was that as an "average" user keeps transferring funds without specifying the index parameter, the wallet will eventually have all the outputs in the main address.

Does this make sense?

Contributor

kenshi84 commented Jun 10, 2017

@xmrgit
Oh, I took your comment the opposite way. My intention of having the index parameter as optional is to allow the user to easily move funds from subaddresses to your main address by simply repeating

sweep_all <your main address>

until there's no subaddress with unlocked balance.

In general, I designed the CLI such that funds in subaddresses tend to accumulate in the main address (by randomly choosing non-zero index first before index=0), because all the change outputs go to the main address, regardless of whether the destination is a standard address or a subaddress. In other words, my intention was that as an "average" user keeps transferring funds without specifying the index parameter, the wallet will eventually have all the outputs in the main address.

Does this make sense?

@knaccc

This comment has been minimized.

Show comment
Hide comment
@knaccc

knaccc Jun 10, 2017

@kenshi84 I'm referring to the terms defined in the previous PR in this comment: #1753 (comment)

Regardless of what terms are used, the two approaches are:

Option 1. The user sees a dropdown selection in the GUI to switch between 'bank accounts', like they would with online banking. Each 'bank account' has its own main balance. You can create alternate receiving addresses for each bank account. I've referred to these 'bank accounts' as subwallets and the 'alternate receiving addresses' as aliases. Both subwallets and aliases are implemented by simply issuing a subaddress per subwallet and a subaddress per subwallet alias.

Option 2. The user does NOT see multiple 'bank accounts' or 'subwallets'. They just see one wallet with a main balance, and then additional different receiving addresses for this wallet. This is how you've implemented things for the CLI so far.

The advantage of Option 1 is that it is less messy.

For example, a user might want to use their wallet for two different purposes: one for personal use (PERSONAL) and another for an eBay like scenario where they are selling things online (SELLING).

For both the PERSONAL and SELLING purposes, the user would create multiple receiving addresses for privacy reasons.

Under Option 1, the user sees two subwallets each with several receiving addresses (aliases).

Under Option 2, the user sees just a big list of different receiving addresses, and unless the user carefully labels them, it will be difficult for them to remember which receiving addresses were used to receive funds for PERSONAL vs SELLING purposes. They may see 20 different receiving addresses, and then have to recall which receiving addresses were given out for PERSONAL vs SELLING.

Option 1 allows the user to easily see a different balance for their PERSONAL vs SELLING subwallets. This is possible because the GUI knows which receiving addresses (aliases) were associated with each subwallet. To see the total funds related to PERSONAL vs SELLING, they would have to not only remember which receiving addresses were used for each PERSONAL/SELLING purpose, but also manually add up funds to figure out the total funds for their PERSONAL vs SELLING activity.

Edit: I've just thought of an Option 3:
Have just one wallet and lots of different receiving addresses (subaddresses). Assign a 'tag' to each subaddress created, e.g. PERSONAL or SELLING. Then the wallet can easily display a subtotal for PERSONAL vs SELLING activity. This would mean there would be no need for 'subwallet' or 'alias' terminology, and we can just call everything a subaddress.

On reflection, I like Option 3 since:
a) No extra terminology (subwallets, aliases)
b) Easier to re-label subaddresses when a wallet is restored form seed and labels have been lost
c) Since Option 3 is so similar to Option 2, and since Option 2 can be converted to Option 3 pretty easily in the future, it means that we could just go for Option 2 (which is exactly what you've already implemented), and Option 3 can be a "maybe" for the future. If we go for Option 2, it'd be nice to have an unused "tag" field available per subaddress for future possible use.

So, in summary, I think we should choose Option 2 or 3 depending on how important we think it is to let users see subtotals for PERSONAL vs SELLING without having to add it up themselves with a calculator.

knaccc commented Jun 10, 2017

@kenshi84 I'm referring to the terms defined in the previous PR in this comment: #1753 (comment)

Regardless of what terms are used, the two approaches are:

Option 1. The user sees a dropdown selection in the GUI to switch between 'bank accounts', like they would with online banking. Each 'bank account' has its own main balance. You can create alternate receiving addresses for each bank account. I've referred to these 'bank accounts' as subwallets and the 'alternate receiving addresses' as aliases. Both subwallets and aliases are implemented by simply issuing a subaddress per subwallet and a subaddress per subwallet alias.

Option 2. The user does NOT see multiple 'bank accounts' or 'subwallets'. They just see one wallet with a main balance, and then additional different receiving addresses for this wallet. This is how you've implemented things for the CLI so far.

The advantage of Option 1 is that it is less messy.

For example, a user might want to use their wallet for two different purposes: one for personal use (PERSONAL) and another for an eBay like scenario where they are selling things online (SELLING).

For both the PERSONAL and SELLING purposes, the user would create multiple receiving addresses for privacy reasons.

Under Option 1, the user sees two subwallets each with several receiving addresses (aliases).

Under Option 2, the user sees just a big list of different receiving addresses, and unless the user carefully labels them, it will be difficult for them to remember which receiving addresses were used to receive funds for PERSONAL vs SELLING purposes. They may see 20 different receiving addresses, and then have to recall which receiving addresses were given out for PERSONAL vs SELLING.

Option 1 allows the user to easily see a different balance for their PERSONAL vs SELLING subwallets. This is possible because the GUI knows which receiving addresses (aliases) were associated with each subwallet. To see the total funds related to PERSONAL vs SELLING, they would have to not only remember which receiving addresses were used for each PERSONAL/SELLING purpose, but also manually add up funds to figure out the total funds for their PERSONAL vs SELLING activity.

Edit: I've just thought of an Option 3:
Have just one wallet and lots of different receiving addresses (subaddresses). Assign a 'tag' to each subaddress created, e.g. PERSONAL or SELLING. Then the wallet can easily display a subtotal for PERSONAL vs SELLING activity. This would mean there would be no need for 'subwallet' or 'alias' terminology, and we can just call everything a subaddress.

On reflection, I like Option 3 since:
a) No extra terminology (subwallets, aliases)
b) Easier to re-label subaddresses when a wallet is restored form seed and labels have been lost
c) Since Option 3 is so similar to Option 2, and since Option 2 can be converted to Option 3 pretty easily in the future, it means that we could just go for Option 2 (which is exactly what you've already implemented), and Option 3 can be a "maybe" for the future. If we go for Option 2, it'd be nice to have an unused "tag" field available per subaddress for future possible use.

So, in summary, I think we should choose Option 2 or 3 depending on how important we think it is to let users see subtotals for PERSONAL vs SELLING without having to add it up themselves with a calculator.

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Jun 10, 2017

Contributor

@knaccc
Thanks a lot for your input.

I'm still not so convinced by your proposal, and in my opinion, this is where I start to feel that having separate wallet files makes more sense. The sole purpose of this PR is to solve the off-chain metadata linkability problem due to address reuse. I didn't intend to improve the user experience of managing multiple accounts in a way similar to today's online banking.

So, in summary, I think we should choose Option 2 or 3 depending on how important we think it is to let users see subtotals for PERSONAL vs SELLING without having to add it up themselves with a calculator.

I think you have one misunderstanding: subtotals in subaddresses are NOT useful for keeping track of balances in a per-purpose basis (e.g. PERSONAL vs SELLING), because whenever you spend funds in those subaddresses, the change always goes to the main address. In other words, you can only keep track of the total incoming transfers to those subaddresses, but not the remaining balances of those subaddresses due to the changes being moved to the main address.

Therefore, I'd rather vote for letting users simply open multiple wallet files separately (either in a new window or a new tab), both for the CLI and GUI (and probably MyMonero).

Contributor

kenshi84 commented Jun 10, 2017

@knaccc
Thanks a lot for your input.

I'm still not so convinced by your proposal, and in my opinion, this is where I start to feel that having separate wallet files makes more sense. The sole purpose of this PR is to solve the off-chain metadata linkability problem due to address reuse. I didn't intend to improve the user experience of managing multiple accounts in a way similar to today's online banking.

So, in summary, I think we should choose Option 2 or 3 depending on how important we think it is to let users see subtotals for PERSONAL vs SELLING without having to add it up themselves with a calculator.

I think you have one misunderstanding: subtotals in subaddresses are NOT useful for keeping track of balances in a per-purpose basis (e.g. PERSONAL vs SELLING), because whenever you spend funds in those subaddresses, the change always goes to the main address. In other words, you can only keep track of the total incoming transfers to those subaddresses, but not the remaining balances of those subaddresses due to the changes being moved to the main address.

Therefore, I'd rather vote for letting users simply open multiple wallet files separately (either in a new window or a new tab), both for the CLI and GUI (and probably MyMonero).

@dan-da

This comment has been minimized.

Show comment
Hide comment
@dan-da

dan-da Jun 10, 2017

Therefore, I'd rather vote for letting users simply open multiple wallet files separately (either in a new window or a new tab), both for the CLI and GUI (and probably MyMonero).

I agree with this. I've long wished that monero cli made it easy to switch between wallets. In fact, if the interface had made that easy for the user eg commands "switchwallet, createwallet, delwallet" then that could have pretty much solved the linkability problem right there for anyone that cares, though with the caveat that separate balances are maintained for each.

Sub-addresses are a nice middle ground that enable a single wallet with a single balance to avoid linkability. @kenshi84 has nailed this I think.

Still, there remains the use case when people WANT separate balances. And there are many good reasons for this. personal vs business. checking vs savings. or to maintain one account per client or source of funds. husband and wife. on and on. Generally: to avoid co-mingling of funds.

When account creation is free/easy people will tend to use it a LOT more. Right now most people are still conditioned to use a single account because opening bank accounts is hard/costly so people just lump all transactions into one or two generally. But crypto is a new paradigm not limited by such constraints.

So I would strongly advocate for a multiple wallet solution. However, afaict that is a separate/orthogonal concern that can be dealt with separately from this pull request.

dan-da commented Jun 10, 2017

Therefore, I'd rather vote for letting users simply open multiple wallet files separately (either in a new window or a new tab), both for the CLI and GUI (and probably MyMonero).

I agree with this. I've long wished that monero cli made it easy to switch between wallets. In fact, if the interface had made that easy for the user eg commands "switchwallet, createwallet, delwallet" then that could have pretty much solved the linkability problem right there for anyone that cares, though with the caveat that separate balances are maintained for each.

Sub-addresses are a nice middle ground that enable a single wallet with a single balance to avoid linkability. @kenshi84 has nailed this I think.

Still, there remains the use case when people WANT separate balances. And there are many good reasons for this. personal vs business. checking vs savings. or to maintain one account per client or source of funds. husband and wife. on and on. Generally: to avoid co-mingling of funds.

When account creation is free/easy people will tend to use it a LOT more. Right now most people are still conditioned to use a single account because opening bank accounts is hard/costly so people just lump all transactions into one or two generally. But crypto is a new paradigm not limited by such constraints.

So I would strongly advocate for a multiple wallet solution. However, afaict that is a separate/orthogonal concern that can be dealt with separately from this pull request.

@xmrgit

This comment has been minimized.

Show comment
Hide comment
@xmrgit

xmrgit Jun 10, 2017

ok @kenshi84 , so sweep_all with optional index makes sense.

is it possible to have some output like this if balance command is used?

[wallet 9xj1hm]: balance
Balance: 20.400000000000, unlocked balance: 20.400000000000  
Balance per subaddress:  
   Index               Balance      Unlocked balance                     Label      Current Outputs    Total Outputs
       0        0.600000000000        0.600000000000              Main address                    1               56
       1        3.600000000000        3.600000000000  Twitter donation address                    2                4
       2        6.600000000000        6.600000000000   GitHub donation address                    3                3
       3        9.600000000000        9.600000000000                                              4                9

current outputs shows count of spendable outputs.
total outputs to know if the sub-address was already used before when the current balance is 0 and/or when we restore wallet from mnemonic seed.

xmrgit commented Jun 10, 2017

ok @kenshi84 , so sweep_all with optional index makes sense.

is it possible to have some output like this if balance command is used?

[wallet 9xj1hm]: balance
Balance: 20.400000000000, unlocked balance: 20.400000000000  
Balance per subaddress:  
   Index               Balance      Unlocked balance                     Label      Current Outputs    Total Outputs
       0        0.600000000000        0.600000000000              Main address                    1               56
       1        3.600000000000        3.600000000000  Twitter donation address                    2                4
       2        6.600000000000        6.600000000000   GitHub donation address                    3                3
       3        9.600000000000        9.600000000000                                              4                9

current outputs shows count of spendable outputs.
total outputs to know if the sub-address was already used before when the current balance is 0 and/or when we restore wallet from mnemonic seed.

@knaccc

This comment has been minimized.

Show comment
Hide comment
@knaccc

knaccc Jun 11, 2017

@kenshi84 @dan-da The reason that this special subaddress scheme needed to be devised in the first place was because the alternative of just scanning for multiple normal Monero addresses is a prohibitively CPU intensive operation.

Therefore allowing the user to open multiple full wallets more easily cannot be a solution, because of the CPU overhead in scanning for multiple wallets.

Therefore, if there is any agreement in the community that there is a need to have multiple balances (per subwallet or per subaddress tag), I think now would be the right time to consider it.

At the moment your implementation is that when funds are spent from a subaddress, the change is sent to the main address. However, it's trivially easy to modify this to ensure that change from funds spent by a subaddress is returned to the subaddress, right?

knaccc commented Jun 11, 2017

@kenshi84 @dan-da The reason that this special subaddress scheme needed to be devised in the first place was because the alternative of just scanning for multiple normal Monero addresses is a prohibitively CPU intensive operation.

Therefore allowing the user to open multiple full wallets more easily cannot be a solution, because of the CPU overhead in scanning for multiple wallets.

Therefore, if there is any agreement in the community that there is a need to have multiple balances (per subwallet or per subaddress tag), I think now would be the right time to consider it.

At the moment your implementation is that when funds are spent from a subaddress, the change is sent to the main address. However, it's trivially easy to modify this to ensure that change from funds spent by a subaddress is returned to the subaddress, right?

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Jun 11, 2017

Contributor

@kenshi84 @dan-da The reason that this special subaddress scheme needed to be devised in the first place was because the alternative of just scanning for multiple normal Monero addresses is a prohibitively CPU intensive operation.

Yes, and that problem was adequately solved by the current implementation.

Therefore, if there is any agreement in the community that there is a need to have multiple balances (per subwallet or per subaddress tag), I think now would be the right time to consider it.

Having multiple balances was not what I originally intended to solve, and it doesn't seem solvable using the cryptographic scheme explained in the OP.

At the moment your implementation is that when funds are spent from a subaddress, the change is sent to the main address. However, it's trivially easy to modify this to ensure that change from funds spent by a subaddress is returned to the subaddress, right?

Technically it's possible only if you transfer to addresses in the standard format a single destination in a standard address format. It'd work in the following way: Bob wants to transfer funds to Charlie's standard address (E1,F1) and David's standard address (E2,F2) while receiving the change to his subaddress (C,D) = (c*G, d*G) where

m = Hs(a || i)
d = b + m
c = a*d

Bob chooses a random scalar s and generates a tx keypair R=r*G as

r = s*d
R = r*G = s*D

and creates the output pubkeys for Charlie and David as

P1 = Hs(r*E1)*G + F1
P2 = Hs(r*E2)*G + F2

and the output pub key for his change as

Q = Hs(s*C)*G + D

This won't work for multi-destination transfers or transfers to subaddresses.

Contributor

kenshi84 commented Jun 11, 2017

@kenshi84 @dan-da The reason that this special subaddress scheme needed to be devised in the first place was because the alternative of just scanning for multiple normal Monero addresses is a prohibitively CPU intensive operation.

Yes, and that problem was adequately solved by the current implementation.

Therefore, if there is any agreement in the community that there is a need to have multiple balances (per subwallet or per subaddress tag), I think now would be the right time to consider it.

Having multiple balances was not what I originally intended to solve, and it doesn't seem solvable using the cryptographic scheme explained in the OP.

At the moment your implementation is that when funds are spent from a subaddress, the change is sent to the main address. However, it's trivially easy to modify this to ensure that change from funds spent by a subaddress is returned to the subaddress, right?

Technically it's possible only if you transfer to addresses in the standard format a single destination in a standard address format. It'd work in the following way: Bob wants to transfer funds to Charlie's standard address (E1,F1) and David's standard address (E2,F2) while receiving the change to his subaddress (C,D) = (c*G, d*G) where

m = Hs(a || i)
d = b + m
c = a*d

Bob chooses a random scalar s and generates a tx keypair R=r*G as

r = s*d
R = r*G = s*D

and creates the output pubkeys for Charlie and David as

P1 = Hs(r*E1)*G + F1
P2 = Hs(r*E2)*G + F2

and the output pub key for his change as

Q = Hs(s*C)*G + D

This won't work for multi-destination transfers or transfers to subaddresses.

@dan-da

This comment has been minimized.

Show comment
Hide comment
@dan-da

dan-da Jun 11, 2017

Having multiple balances was not what I originally intended to solve, and it doesn't seem solvable using the cryptographic scheme explained in the OP.

That's unfortunuate. Perhaps a problem for another day then. I do know that in bitcoin wallets like mycelium, copay, etc I really love being able to easily create a new named wallet and not even have to worry about making a backup after the first one. It's very powerful.

dan-da commented Jun 11, 2017

Having multiple balances was not what I originally intended to solve, and it doesn't seem solvable using the cryptographic scheme explained in the OP.

That's unfortunuate. Perhaps a problem for another day then. I do know that in bitcoin wallets like mycelium, copay, etc I really love being able to easily create a new named wallet and not even have to worry about making a backup after the first one. It's very powerful.

@knaccc

This comment has been minimized.

Show comment
Hide comment
@knaccc

knaccc Jun 11, 2017

@kenshi84 When change is returned when funds are spent to someone else's subaddress, at the moment change is sent to:

Q = Hs(x*R)*G + Y

Where x is the sender's private view key and Y is the senders' public spend key for their main address.

Why can't Y simply be substituted for one of the public spend keys associated with one of the sender's subaddresses?

knaccc commented Jun 11, 2017

@kenshi84 When change is returned when funds are spent to someone else's subaddress, at the moment change is sent to:

Q = Hs(x*R)*G + Y

Where x is the sender's private view key and Y is the senders' public spend key for their main address.

Why can't Y simply be substituted for one of the public spend keys associated with one of the sender's subaddresses?

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Jun 11, 2017

Contributor

@knaccc

Why can't Y simply be substituted for one of the public spend keys associated with one of the sender's subaddresses?

I was missing that point! Yes, then it seems possible to have your change sent to any of your subaddress.

Contributor

kenshi84 commented Jun 11, 2017

@knaccc

Why can't Y simply be substituted for one of the public spend keys associated with one of the sender's subaddresses?

I was missing that point! Yes, then it seems possible to have your change sent to any of your subaddress.

@knaccc

This comment has been minimized.

Show comment
Hide comment
@knaccc

knaccc Jun 11, 2017

@kenshi84 OK great, I'm not near an IRC screen at the moment but I'll bring this up on IRC at some point perhaps later tonight to get some feedback on whether it's deemed worthwhile to have the concept of 'subwallet' style multiple balances or not.

knaccc commented Jun 11, 2017

@kenshi84 OK great, I'm not near an IRC screen at the moment but I'll bring this up on IRC at some point perhaps later tonight to get some feedback on whether it's deemed worthwhile to have the concept of 'subwallet' style multiple balances or not.

@knaccc

This comment has been minimized.

Show comment
Hide comment
@knaccc

knaccc Jun 11, 2017

@kenshi84 Some progress was made on IRC. There was consensus that it'd be a good idea to have the concept of different 'bank accounts' somehow.

I've created this mockup for selection of these 'bank accounts' in the GUI. Note that in the mockup, the different wallets are chosen in the top-left dropdown, and each of these wallets are able to have multiple receiving addresses as displayed in the right hand side of the screenshot.
http://imgur.com/a/wHRF9

@Jaqueeee has proposed creating a new home screen instead of having the "send" section as the home screen, which will allow wallet selection and renaming etc.

For simplicity, I've called it "Wallet selection", so the users will see that they have the ability to create multiple "wallets" instead of learning a new term "subwallet".

I've also referred to subwallet aliases as simply "receiving addresses".

On further reflection, I think your implementation is just fine and that I'm sure eventually you'll be able to display a list of subaddresses along with a label and the name of the subwallet they're each associated with.

I think it's necessary to send change back to the same subaddress which originally received it to avoid user confusion. Otherwise they'd spend 1 XMR out of the 5 XMR that was sent to them, and then panic when that subaddress suddenly shows a balance of zero because change was being sent elsewhere.

knaccc commented Jun 11, 2017

@kenshi84 Some progress was made on IRC. There was consensus that it'd be a good idea to have the concept of different 'bank accounts' somehow.

I've created this mockup for selection of these 'bank accounts' in the GUI. Note that in the mockup, the different wallets are chosen in the top-left dropdown, and each of these wallets are able to have multiple receiving addresses as displayed in the right hand side of the screenshot.
http://imgur.com/a/wHRF9

@Jaqueeee has proposed creating a new home screen instead of having the "send" section as the home screen, which will allow wallet selection and renaming etc.

For simplicity, I've called it "Wallet selection", so the users will see that they have the ability to create multiple "wallets" instead of learning a new term "subwallet".

I've also referred to subwallet aliases as simply "receiving addresses".

On further reflection, I think your implementation is just fine and that I'm sure eventually you'll be able to display a list of subaddresses along with a label and the name of the subwallet they're each associated with.

I think it's necessary to send change back to the same subaddress which originally received it to avoid user confusion. Otherwise they'd spend 1 XMR out of the 5 XMR that was sent to them, and then panic when that subaddress suddenly shows a balance of zero because change was being sent elsewhere.

@xmrgit

This comment has been minimized.

Show comment
Hide comment
@xmrgit

xmrgit Jun 12, 2017

I dont think this will give a good user experience when users are restoring their wallet from seed.
nobody can memorize which subaddress belongs to which wallet. it will only confuse most people.
another subwallet scheme (where each subwallet still has subaddresses) would be more suitable in my opinion.

xmrgit commented Jun 12, 2017

I dont think this will give a good user experience when users are restoring their wallet from seed.
nobody can memorize which subaddress belongs to which wallet. it will only confuse most people.
another subwallet scheme (where each subwallet still has subaddresses) would be more suitable in my opinion.

@moneroexamples

This comment has been minimized.

Show comment
Hide comment
@moneroexamples

moneroexamples Oct 21, 2017

Contributor

@kenshi84

Just added tentatively decoding outputs and proving txs to the onion explorer for subaddress.

Just wanted to confirm, that there is no such thing as integrated subaddresses? Subaddreses are meant to replace integrated_address?

Contributor

moneroexamples commented Oct 21, 2017

@kenshi84

Just added tentatively decoding outputs and proving txs to the onion explorer for subaddress.

Just wanted to confirm, that there is no such thing as integrated subaddresses? Subaddreses are meant to replace integrated_address?

@JollyMort

This comment has been minimized.

Show comment
Hide comment
@JollyMort

JollyMort Oct 21, 2017

Contributor

@moneroexamples that's right, and fyi it was discussed further up

Contributor

JollyMort commented Oct 21, 2017

@moneroexamples that's right, and fyi it was discussed further up

@@ -406,8 +473,20 @@ struct Wallet
virtual ConnectionStatus connected() const = 0;
virtual void setTrustedDaemon(bool arg) = 0;
virtual bool trustedDaemon() const = 0;
virtual uint64_t balance() const = 0;
virtual uint64_t unlockedBalance() const = 0;

This comment has been minimized.

@Jaqueeee

Jaqueeee Oct 22, 2017

Contributor

@kenshi84 would it somehow be possible to keep the old address(), balance(), unlockedBalance() functions and make them use default account/address indices? I'm aware of monero-project/monero-gui#908, but there are also other wallets using this API (monerujo for example). @m2049r @luigi1111 @moneromooo-monero

@Jaqueeee

Jaqueeee Oct 22, 2017

Contributor

@kenshi84 would it somehow be possible to keep the old address(), balance(), unlockedBalance() functions and make them use default account/address indices? I'm aware of monero-project/monero-gui#908, but there are also other wallets using this API (monerujo for example). @m2049r @luigi1111 @moneromooo-monero

This comment has been minimized.

@m2049r

m2049r Oct 22, 2017

Contributor

Whoaa!!! Guys, please don't kill API methods "just like that". Deprecate them and give us at least one release (better 2) time to catch up. Otherwise it's impossible to keep uninterrupted service. Also, please document deprecations clearly & prominently in the release notes!

Thanks for the ping @Jaqueeee .

@m2049r

m2049r Oct 22, 2017

Contributor

Whoaa!!! Guys, please don't kill API methods "just like that". Deprecate them and give us at least one release (better 2) time to catch up. Otherwise it's impossible to keep uninterrupted service. Also, please document deprecations clearly & prominently in the release notes!

Thanks for the ping @Jaqueeee .

This comment has been minimized.

@kenshi84

kenshi84 Oct 23, 2017

Contributor

@Jaqueeee
Sorry for making abrupt changes to the wallet API, and thank you for quickly making a patch #2703 .

@kenshi84

kenshi84 Oct 23, 2017

Contributor

@Jaqueeee
Sorry for making abrupt changes to the wallet API, and thank you for quickly making a patch #2703 .

@kenshi84 kenshi84 changed the title from [Needs testing] Subaddresses to Subaddresses Oct 24, 2017

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Oct 24, 2017

Contributor

@moneroexamples

Just added tentatively decoding outputs and proving txs to the onion explorer for subaddress.

Cool! Perhaps it'd be nice to have a little note on the "decode outputs" page saying that you need to provide the appropriate subaddress that you think the fund is sent to; e.g. when you sent funds using an account whose index is i>0, you can decode the change output by providing the subaddress i/0 (i.e., what you get when you type account switch i and then address). I hope this isn't too confusing for new users:)

Contributor

kenshi84 commented Oct 24, 2017

@moneroexamples

Just added tentatively decoding outputs and proving txs to the onion explorer for subaddress.

Cool! Perhaps it'd be nice to have a little note on the "decode outputs" page saying that you need to provide the appropriate subaddress that you think the fund is sent to; e.g. when you sent funds using an account whose index is i>0, you can decode the change output by providing the subaddress i/0 (i.e., what you get when you type account switch i and then address). I hope this isn't too confusing for new users:)

@moneroexamples

This comment has been minimized.

Show comment
Hide comment
@moneroexamples

moneroexamples Oct 24, 2017

Contributor

Will work more on this more. For now just added quick support to test its feasibility. So instead of your real address+viewkey, you can also use subaddress with viewkey now. The changes are not in master branch, but in devel branch: https://github.com/moneroexamples/onion-monero-blockchain-explorer/tree/devel

Probably will have more questions as time goes :-)

Contributor

moneroexamples commented Oct 24, 2017

Will work more on this more. For now just added quick support to test its feasibility. So instead of your real address+viewkey, you can also use subaddress with viewkey now. The changes are not in master branch, but in devel branch: https://github.com/moneroexamples/onion-monero-blockchain-explorer/tree/devel

Probably will have more questions as time goes :-)

@moneroexamples

This comment has been minimized.

Show comment
Hide comment
@moneroexamples

moneroexamples Nov 10, 2017

Contributor

@kenshi84

Where in the code is the part about making txs to a subaddress as discribed in Sending to a subaddress ?

Want to see what is different from making txs to a regular address.

Thx

Contributor

moneroexamples commented Nov 10, 2017

@kenshi84

Where in the code is the part about making txs to a subaddress as discribed in Sending to a subaddress ?

Want to see what is different from making txs to a regular address.

Thx

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Nov 10, 2017

Contributor

@moneroexamples
If you look at simplewallet.cpp or wallet_rpc_server.cpp, after parsing the address string using cryptonote::get_account_address_from_str, the is_subaddress flag gets passed to a struct cryptonote::tx_destination_entry which is then passed to wallet2::create_transactions_2. From there, this data is carried to wallet2::transfer_selected_rct and then to cryptonote::construct_tx_and_get_tx_key where the is_subaddress flag is finally used to perform the modified crypto scheme. Is this clear enough?

Contributor

kenshi84 commented Nov 10, 2017

@moneroexamples
If you look at simplewallet.cpp or wallet_rpc_server.cpp, after parsing the address string using cryptonote::get_account_address_from_str, the is_subaddress flag gets passed to a struct cryptonote::tx_destination_entry which is then passed to wallet2::create_transactions_2. From there, this data is carried to wallet2::transfer_selected_rct and then to cryptonote::construct_tx_and_get_tx_key where the is_subaddress flag is finally used to perform the modified crypto scheme. Is this clear enough?

@moneroexamples

This comment has been minimized.

Show comment
Hide comment
@moneroexamples

moneroexamples Nov 10, 2017

Contributor

@kenshi84

Thanks. i will look into it. If have any further questions, I will ask:-)

Contributor

moneroexamples commented Nov 10, 2017

@kenshi84

Thanks. i will look into it. If have any further questions, I will ask:-)

@moneroexamples

This comment has been minimized.

Show comment
Hide comment
@moneroexamples

moneroexamples Nov 13, 2017

Contributor

@kenshi84

For future reference, based on #2056 (comment)

The key parts for making a tx to a single subaddress are;

https://github.com/monero-project/monero/blob/master/src/cryptonote_core/cryptonote_tx_utils.cpp#L323

    // if this is a single-destination transfer to a subaddress, we set the tx pubkey to R=s*D
    if (num_stdaddresses == 0 && num_subaddresses == 1)
    {
      txkey.pub = rct::rct2pk(rct::scalarmultKey(
              rct::pk2rct(single_dest_subaddress.m_spend_public_key), rct::sk2rct(txkey.sec))
      );

      remove_field_from_tx_extra(tx.extra, typeid(tx_extra_pub_key));

      add_tx_pub_key_to_extra(tx, txkey.pub);
    }

and

https://github.com/monero-project/monero/blob/master/src/cryptonote_core/cryptonote_tx_utils.cpp#L357

      if (change_addr && dst_entr.addr == *change_addr)
      {
        // sending change to yourself; derivation = a*R
        r = crypto::generate_key_derivation(txkey.pub, sender_account_keys.m_view_secret_key, derivation);
        CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey.pub << ", " << sender_account_keys.m_view_secret_key << ")");
      }
      else
      {
        // sending to the recipient; derivation = r*A (or s*C in the subaddress scheme)
          
        r = crypto::generate_key_derivation(
                dst_entr.addr.m_view_public_key, 
                dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : txkey.sec, 
                derivation);
          
        CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << (dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : txkey.sec) << ")");
      }

For a tx to a single subaddresses need to generate new txkey.pub, and use different derivation for a subaddress/regular_address, and when sending change to oneself.

I think these are the two key changes in tx sending due to subaddresses.

Contributor

moneroexamples commented Nov 13, 2017

@kenshi84

For future reference, based on #2056 (comment)

The key parts for making a tx to a single subaddress are;

https://github.com/monero-project/monero/blob/master/src/cryptonote_core/cryptonote_tx_utils.cpp#L323

    // if this is a single-destination transfer to a subaddress, we set the tx pubkey to R=s*D
    if (num_stdaddresses == 0 && num_subaddresses == 1)
    {
      txkey.pub = rct::rct2pk(rct::scalarmultKey(
              rct::pk2rct(single_dest_subaddress.m_spend_public_key), rct::sk2rct(txkey.sec))
      );

      remove_field_from_tx_extra(tx.extra, typeid(tx_extra_pub_key));

      add_tx_pub_key_to_extra(tx, txkey.pub);
    }

and

https://github.com/monero-project/monero/blob/master/src/cryptonote_core/cryptonote_tx_utils.cpp#L357

      if (change_addr && dst_entr.addr == *change_addr)
      {
        // sending change to yourself; derivation = a*R
        r = crypto::generate_key_derivation(txkey.pub, sender_account_keys.m_view_secret_key, derivation);
        CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << txkey.pub << ", " << sender_account_keys.m_view_secret_key << ")");
      }
      else
      {
        // sending to the recipient; derivation = r*A (or s*C in the subaddress scheme)
          
        r = crypto::generate_key_derivation(
                dst_entr.addr.m_view_public_key, 
                dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : txkey.sec, 
                derivation);
          
        CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << (dst_entr.is_subaddress && need_additional_txkeys ? additional_txkey.sec : txkey.sec) << ")");
      }

For a tx to a single subaddresses need to generate new txkey.pub, and use different derivation for a subaddress/regular_address, and when sending change to oneself.

I think these are the two key changes in tx sending due to subaddresses.

moneroexamples added a commit to moneroexamples/openmonero that referenced this pull request Nov 13, 2017

moneroexamples added a commit to moneroexamples/openmonero that referenced this pull request Nov 13, 2017

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Nov 13, 2017

Contributor

@moneroexamples
Nice work! I gave some comments in the commit. I'm looking forward to it working :)

Contributor

kenshi84 commented Nov 13, 2017

@moneroexamples
Nice work! I gave some comments in the commit. I'm looking forward to it working :)

@moneroexamples

This comment has been minimized.

Show comment
Hide comment
@moneroexamples

moneroexamples Nov 13, 2017

Contributor

@kenshi84
Thanks. onion explorer with help of @stoffu and yours seems to work well with decoding and proving subaddress (testnet link: http://139.162.32.245:8082/). So slowly can start looking into open monero.

Contributor

moneroexamples commented Nov 13, 2017

@kenshi84
Thanks. onion explorer with help of @stoffu and yours seems to work well with decoding and proving subaddress (testnet link: http://139.162.32.245:8082/). So slowly can start looking into open monero.

@moneroexamples

This comment has been minimized.

Show comment
Hide comment
@moneroexamples

moneroexamples Jan 25, 2018

Contributor

@kenshi84

Have new question.

How do I prove change returned to myself using private_tx_key? Let me explain what I mean using example.

When A makes tx to regular address of B, he will receiver a private tx key (obtained using get_tx_key in A's wallet). Using the key, A can prove to B (using his public address) that he sent to B what he said. Also, A can use his own public address with the same key and see the change returned to A.

Now, when A makes tx to sub-address of B, the second part (i.e., checking the change returned to A using the private tx key) does not seem to work. I know that A can use his regular address + his private viewkey to check the change. But I am curious why it does not work with tx private key when sending to a sub-address of B, but it works when sending to regular address of B.

Contributor

moneroexamples commented Jan 25, 2018

@kenshi84

Have new question.

How do I prove change returned to myself using private_tx_key? Let me explain what I mean using example.

When A makes tx to regular address of B, he will receiver a private tx key (obtained using get_tx_key in A's wallet). Using the key, A can prove to B (using his public address) that he sent to B what he said. Also, A can use his own public address with the same key and see the change returned to A.

Now, when A makes tx to sub-address of B, the second part (i.e., checking the change returned to A using the private tx key) does not seem to work. I know that A can use his regular address + his private viewkey to check the change. But I am curious why it does not work with tx private key when sending to a sub-address of B, but it works when sending to regular address of B.

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Jan 25, 2018

Contributor

@moneroexamples

I know that A can use his regular address + his private viewkey to check the change. But I am curious why it does not work with tx private key when sending to a sub-address of B, but it works when sending to regular address of B.

This is due to the particular way tx public keys are computed when sending funds to subaddresses. As in the OP, when Alice's wallet (view, spend) = (X, Y) sends funds to Bob's subaddress (C, D), the output key P for Bob is computed as

P = Hs(s*C)*G + D

where s is the tx secret key, while the change output key Q back to Alice is computed as

Q = Hs(x*R)*G + Y

where R = s*D is the tx public key. This formulation makes it impossible to use the traditional way of proving payments using the tx secret key which is to use

Q' = Hs(s*X)*G + Y

because x*R == x*s*D != s*X and thus Q != Q'.

Contributor

kenshi84 commented Jan 25, 2018

@moneroexamples

I know that A can use his regular address + his private viewkey to check the change. But I am curious why it does not work with tx private key when sending to a sub-address of B, but it works when sending to regular address of B.

This is due to the particular way tx public keys are computed when sending funds to subaddresses. As in the OP, when Alice's wallet (view, spend) = (X, Y) sends funds to Bob's subaddress (C, D), the output key P for Bob is computed as

P = Hs(s*C)*G + D

where s is the tx secret key, while the change output key Q back to Alice is computed as

Q = Hs(x*R)*G + Y

where R = s*D is the tx public key. This formulation makes it impossible to use the traditional way of proving payments using the tx secret key which is to use

Q' = Hs(s*X)*G + Y

because x*R == x*s*D != s*X and thus Q != Q'.

@moneroexamples

This comment has been minimized.

Show comment
Hide comment
@moneroexamples

moneroexamples Jan 25, 2018

Contributor

@kenshi84

Thanks. But proving change using tx_private_key(s) works when making tx to multiple addresses/subaddress. It only does not work when sending to a single subaddress. My guess is that when sending to multiple subaddresses/addresses in a single tx, extra tx_public_keys and extra private_tx_keys are generated and saved. This does not happen when sending to a single subaddress. Shouldn't there be some extra tx_private_key or tx_public_key also used in this case?

Contributor

moneroexamples commented Jan 25, 2018

@kenshi84

Thanks. But proving change using tx_private_key(s) works when making tx to multiple addresses/subaddress. It only does not work when sending to a single subaddress. My guess is that when sending to multiple subaddresses/addresses in a single tx, extra tx_public_keys and extra private_tx_keys are generated and saved. This does not happen when sending to a single subaddress. Shouldn't there be some extra tx_private_key or tx_public_key also used in this case?

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Jan 25, 2018

Contributor

@moneroexamples

Your understanding is correct.

Shouldn't there be some extra tx_private_key or tx_public_key also used in this case?

That would make a 2-output tx to a subaddress distinguishable from other typical 2-output txes to standard addresses, so no.

Contributor

kenshi84 commented Jan 25, 2018

@moneroexamples

Your understanding is correct.

Shouldn't there be some extra tx_private_key or tx_public_key also used in this case?

That would make a 2-output tx to a subaddress distinguishable from other typical 2-output txes to standard addresses, so no.

@moneroexamples

This comment has been minimized.

Show comment
Hide comment
@moneroexamples

moneroexamples Jan 25, 2018

Contributor

@kenshi84

Thanks. Makes sense for 2-output. But what about a 3-output tx with at least one subaddress? Such txs also stand out, due to the additional tx public keys stored in the extra field, dont they?.

Contributor

moneroexamples commented Jan 25, 2018

@kenshi84

Thanks. Makes sense for 2-output. But what about a 3-output tx with at least one subaddress? Such txs also stand out, due to the additional tx public keys stored in the extra field, dont they?.

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Jan 26, 2018

Contributor

@moneroexamples

You're right that transfers to multiple destinations including subaddresses will stand out due to additional tx keys. Between the following two options:

  1. Don't allow sending to multiple destinations that include subaddresses.

    • Pros: No need for additional tx keys (= txes are perfectly indistinguishable).
    • Cons: Limited ease of use (particularly for mining pools, where people can't use their subaddresses for payouts)
  2. Enable sending to multiple destinations that include subaddresses by introducing additional tx keys.

    • Pros: Ease of use.
    • Cons: Those txes with multiple destinations including subaddresses become distinguishable from other multi-destination txes that are only going to standard addresses.

we decided to choose the latter after a thorough discussion (credit to @knaccc), anticipating that the use of subaddresses will be the norm in the future.

Contributor

kenshi84 commented Jan 26, 2018

@moneroexamples

You're right that transfers to multiple destinations including subaddresses will stand out due to additional tx keys. Between the following two options:

  1. Don't allow sending to multiple destinations that include subaddresses.

    • Pros: No need for additional tx keys (= txes are perfectly indistinguishable).
    • Cons: Limited ease of use (particularly for mining pools, where people can't use their subaddresses for payouts)
  2. Enable sending to multiple destinations that include subaddresses by introducing additional tx keys.

    • Pros: Ease of use.
    • Cons: Those txes with multiple destinations including subaddresses become distinguishable from other multi-destination txes that are only going to standard addresses.

we decided to choose the latter after a thorough discussion (credit to @knaccc), anticipating that the use of subaddresses will be the norm in the future.

@moneroexamples

This comment has been minimized.

Show comment
Hide comment
@moneroexamples

moneroexamples Jan 26, 2018

Contributor

@kenshi84

Thanks. Its clear now. One more argument for option 2, would be that multiple-output txs are much less common than 2-outputs one. Also in e.g., 10-output tx, its unclear if there are 1 or 9 subaddress, whereas in 2-output, one would immediately know that you are dealing with a subadddress due to extra keys.

Contributor

moneroexamples commented Jan 26, 2018

@kenshi84

Thanks. Its clear now. One more argument for option 2, would be that multiple-output txs are much less common than 2-outputs one. Also in e.g., 10-output tx, its unclear if there are 1 or 9 subaddress, whereas in 2-output, one would immediately know that you are dealing with a subadddress due to extra keys.

@Technohacker

This comment has been minimized.

Show comment
Hide comment
@Technohacker

Technohacker Apr 13, 2018

Contributor

Just wanted to make my understanding clear,

  1. Why is the view secret key (and not the spend secret key) used in subaddress generation?
  2. Can the spend secret key be used instead?

Thanks :)

Contributor

Technohacker commented Apr 13, 2018

Just wanted to make my understanding clear,

  1. Why is the view secret key (and not the spend secret key) used in subaddress generation?
  2. Can the spend secret key be used instead?

Thanks :)

@kenshi84

This comment has been minimized.

Show comment
Hide comment
@kenshi84

kenshi84 Apr 13, 2018

Contributor
  1. Why is the view secret key used in subaddress generation?

Because we'd like watch-only wallets to be able to recognize incoming transfers to subaddresses.

  1. Can the spend secret key be used instead?

That would mean only full wallets can see incoming transfers to subaddresses. If that's what you want, sure you can do so by customizing the code yourself. But your idea is unlikely to be adopted because it doesn't seem useful.

Contributor

kenshi84 commented Apr 13, 2018

  1. Why is the view secret key used in subaddress generation?

Because we'd like watch-only wallets to be able to recognize incoming transfers to subaddresses.

  1. Can the spend secret key be used instead?

That would mean only full wallets can see incoming transfers to subaddresses. If that's what you want, sure you can do so by customizing the code yourself. But your idea is unlikely to be adopted because it doesn't seem useful.

@Technohacker

This comment has been minimized.

Show comment
Hide comment
@Technohacker

Technohacker Apr 13, 2018

Contributor

@kenshi84 Ah okay, thanks for the clarification :)

Contributor

Technohacker commented Apr 13, 2018

@kenshi84 Ah okay, thanks for the clarification :)

@krtschmr

This comment has been minimized.

Show comment
Hide comment
@krtschmr

krtschmr Apr 22, 2018

we need a function to explicit generate a subadress with given i.

since whitespaces are allowed in the label i would suggest

address index 18034

krtschmr commented Apr 22, 2018

we need a function to explicit generate a subadress with given i.

since whitespaces are allowed in the label i would suggest

address index 18034
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment