Multiple Wallets, one computer (multiple accounts)

9 messages BitcoinTalk bytemaster, Satoshi Nakamoto, Gavin Andresen, nelisky, grondilu, SmokeTooMuch August 1, 2010 — October 25, 2010
bytemaster August 1, 2010 Source · Permalink

I want to have multiple “accounts” with unique balances and to send and receive coins on a per-account basis. The equiv. of having multiple wallets running at the same time.

It would help to simply list the balance for each ‘receiving address’ and to specify a ‘source’ address when sending coins.

Gavin Andresen September 27, 2010 Source · Permalink

The “label” mechanism (setlabel / getreceivedbylabel) is supposed to meet this need, but only solves part of the problem.

If the API was extended as I describe below, would it solve the same problems as having multiple wallets?

Proposal:

  • new send method: send TO a given bitcoin address specifically FROM the bitcoins sent to
  • add optional [label] param to getbalance.
  • new method: listsentbylabel (returns array of [ “address” : “bcaddresssentto”, “amount” : x.yz, “confirmations”: n ])

Each customer “account” would be a bitcoin

Create account / create new address for account: getnewaddress [account_id_label] … tell user “fund your account by sending coins to {the address returned}”

Customer withdraws/spends: sendfrom [account_id_label] [address] [amount] (FAILS if balance for that account too low)

Show customer their balance: getbalance [account_id_label]

Show customer their transactions in/out listreceivedbylabel [account_id_label] listsentbylabel [account_id_label]


Seems to me this would be a much better direction to go in, rather than having separate wallet.dat files for each customer. At the very least, backing up thousands of customer’s wallet files would be inefficient and error-prone, and constantly switching between them would also be incredibly inefficient.

nelisky September 27, 2010 Source · Permalink

Quote from: gavinandresen on September 27, 2010, 03:14:55 PM

The “label” mechanism (setlabel / getreceivedbylabel) is supposed to meet this need, but only solves part of the problem.

If the API was extended as I describe below, would it solve the same problems as having multiple wallets?

Proposal:

  • new send method: send TO a given bitcoin address specifically FROM the bitcoins sent to (change generated would be automatically tagged with )
  • add optional [label] param to getbalance.
  • new method: listsentbylabel (returns array of [ “address” : “bcaddresssentto”, “amount” : x.yz, “confirmations”: n ])

Each customer “account” would be a bitcoin . Account handling would look like:

Create account / create new address for account: getnewaddress [account_id_label] … tell user “fund your account by sending coins to {the address returned}”

Customer withdraws/spends: sendfrom [account_id_label] [address] [amount] (FAILS if balance for that account too low)

Show customer their balance: getbalance [account_id_label]

Show customer their transactions in/out listreceivedbylabel [account_id_label] listsentbylabel [account_id_label]


Seems to me this would be a much better direction to go in, rather than having separate wallet.dat files for each customer. At the very least, backing up thousands of customer’s wallet files would be inefficient and error-prone, and constantly switching between them would also be incredibly inefficient.

That is a much better approach, agreed. Assuming one label spans multiple addresses, so a client can accept transactions from an imported priv key (this being discussed on another thread), it seems to fit my needs perfectly, with only one small caveat which is internal transfers; say I use this approach for the lottery users (though that is not my use case, I actually would be more about site separation than user separation, but still):

  • Each account has on inbound address, annotated with the login label
  • Every time a user withdraws, I use the sendfrom mechanism you describe
  • The user hits the jackpot, but the prize is actually held in multiple users’ accounts so a) I need to, when users buy tickets, move the amount to a separate address (forces external transaction, sucks) b) I leave coins where they are, and then on payout I make a normal sendtoaddress (both external transaction and breaks the label accounting logic) c) I leave coins where they are, payouts do nothing to the wallet, withdrawals do as many transactions as needed from each user account (what a nightmare!)

I don’t see any good option here, and the best one, if I’m doing external transactions anyway, is a). I can trust these transactions with 0 blocks confirmed, because I’m both the sender and the recipient, and this would keep the accounts/labels in check, which serves as a great verification to the overall balances. Can you think of any alternative?

Gavin Andresen September 27, 2010 Source · Permalink

Separate “accounts” (addresses with labels) to accumulate Jackpots is the right idea. Users buy tickets, bitcoins are moved to the appropriate Jackpot account. When a Jackpot is won, transactions flow out of its account back to whoever won.

nelisky September 27, 2010 Source · Permalink

Quote from: gavinandresen on September 27, 2010, 05:10:33 PM

Separate “accounts” (addresses with labels) to accumulate Jackpots is the right idea. Users buy tickets, bitcoins are moved to the appropriate Jackpot account. When a Jackpot is won, transactions flow out of its account back to whoever won.

Yeah, it is quite obvious. I suffer for over optimization obsession syndrome Smiley I feel that as data flows only inside the application there’s no need to register transactions and put that ‘extra load’ on the system, but quite frankly the extra load is perfectly ignorable, and the transactions help keep everything tidy. Are you planning to do anything on this regard? I’m sure I can find my way around to do it myself, it will just take time, but I don’t want to duplicate any work though.

Satoshi Nakamoto October 24, 2010 Source · Permalink

I have the beginning of something like this.  It’s mostly like what Gavin described.

Some more rpc interface:

move    Move from one internal account to another.  I think blank account name ("") will be your default account.  If you sell something to a user, you could do move “theiraccount” "" 123.45.    Is “move” the best name for this?  I shied away from “transfer” because that sounds too close to sending a transaction.

I’m thinking a new function getaccountaddress instead of overloading getnewaddress:

getaccountaddress    Gives you an address allocated from getnewaddress .  It’ll keep giving the same address until something is received on the address, then it allocates a new address.  (It automatically does what the sample code I posted some time ago did)

Would these commands make it possible in simple cases to implement your website without needing a database of your own?

grondilu October 24, 2010 Source · Permalink

Wouldn’t it be much simpler to be able to run several instances of bitcoin, each of them running on a specific “wallet.dat” file ?

I mean, we would just add a —wallet long option to the client/server app. The name of your account would be the name of your wallet file.

SmokeTooMuch October 24, 2010 Source · Permalink

Quote from: bytemaster on August 01, 2010, 08:14:29 PM

I want to have multiple “accounts” with unique balances and to send and receive coins on a per-account basis. The equiv. of having multiple wallets running at the same time.

It would help to simply list the balance for each ‘receiving address’ and to specify a ‘source’ address when sending coins.

use -datadir and change the port on the source code and then use a different dir and port for every bitcoin instance

Satoshi Nakamoto October 25, 2010 Source · Permalink

Here’s some pseudocode of how you would use the account based commands.  It sure makes website integration a lot easier.

print "send to " + getaccountaddress(username) + " to fund your account"
print "balance: " + getbalance(username, 0)
print "available balance: " + getbalance(username, 6)
// if you make a sale, move the money out of their account
move(username, "", amount, 6)

// withdrawal
sendfrom(username, bitcoinaddress, amount, 6)