Handling change addresses without using rawtransactions?

0

Since I'm using the wonderful accounts feature which is soon to be deprecated (shame on me, i know - but i simply didn't have resources and time as a single person to do an internal accounting system in a few weeks alongside everything else the project contains, this is a school project and will not be deployed), i was wondering how to handle sending transactions & change addresses, without using raw transactions.

Would the following work

SendMany(fromacc, toaddress: amount, 1, "comment", subtractfee)

(I'm planning to use SendMany for single transactions, because it has the subtractfee parameter compared to SendFrom).

Use the resulting TXID to query Blockcypher API (https://api.blockcypher.com/v1/btc/main/txs/b7bf53a74a4e4cb61ab523cc002fc4cea83fb359471d02b212d947cf86fe6077) and "grab" the change address from there (Since Bitcoin Core doesn't allow this wihout using rawtransactions?)

VerifyAddress(changeaddress)
SetAccount(account, changeaddress)

Which means that GetBalance(account) should show the correct balance of the account and not 0?

Or should i really not do that and use rawtransactions instead? :-)

edit:

So i just realised that i confused the subtractfee parameter in SendMany from the one in SendToAddress (which is what i need), so i suppose i need to use that instead.

would using:

$balance = getBalance($myaccount)
move("", $myaccount, $sendingamount, "", "comment")
SendToAddress($receiveaddr, $sendingamount, "comment", "commentto", 1, 0, 6)

do the the blockcypher grab TX id, verifyaddress and set account here

OR

$newBalance = getBalance($myaccount)
$change = $balance - $sendingamount
move("", $myaccount, $change, "", "comment")

Work in this case and would listunspent show the amount under the right account (not "")?

Also here is what I'm trying to do from a user perspective: https://imgur.com/a/IHrF4vI

Peter Dalby

Posted 2018-05-16T14:02:42.597

Reputation: 5

Why do you need to know the change address?Andrew Chow 2018-05-16T16:24:19.837

Instead of asking about the approach that you want to do, you should ask about what it is that you want to accomplish. Otherwise this is an XY problem (http://xyproblem.info/) and it doesn't really make sense to people who can provide you an answer. As it is right now, I don't understand what you are trying to do and what the problem actually is so I cannot provide you a good answer.

Andrew Chow 2018-05-16T16:28:27.907

Yeah, i apologize. I've been quiet confused about sending transactions and the heat has gotten to me today. I would like for a user with an account to be able to transfer what is available in their balance, that they have received from a generated address. The fee should be deducted from what they're sending, so the receiver gets less. The change address which receives the change should be accessable by the account and should somehow be able to be shown in their balance. So if i send 1BTC of a balance of 2BTC, i would like for my balance to show 1BTC, not 0BTC.Peter Dalby 2018-05-16T17:01:52.293

I suppose i have to use raw transactions to accomplish this and directly specify which inputs to use for the transaction? i just heard that it's very likely to make mistakes when using this, and it's for advanced use only. I'd like to keep it as simple as if at all possible... :-)Peter Dalby 2018-05-16T17:07:10.037

Also in the example the 2BTC balance should be considered one input which would mean that the entire balance would be empitied for the user when trying to send some of it. I need to show the expected balance :-)Peter Dalby 2018-05-16T17:38:22.837

Answers

0

It sounds like there is a misunderstanding of how accounts work (which is not surprising given that the accounts system is very unintuitive).

First of all, addresses are only tied to accounts for receiving, not sending. So when you send from an account, any input associated with any address in the wallet can be selected for the transaction. During that send, the account's balance is deducted by exactly the amount that was sent. Change goes back into the wallet and has no effect on the balance as it was not sent from the account.

The account field in listunspent is slightly misleading as outputs are really not associated with accounts at all. When you send from an account, ANY output can be chosen as inputs for the transaction, not just ones that are part of the account.

When sending, because you know the recipients address, you can use the subtractFeeFrom parameters of sendmany or sendtoaddress to specify that the fee will be subtracted from the specified addresses (i.e. the recipients). This should still deduct from the account balance.

Andrew Chow

Posted 2018-05-16T14:02:42.597

Reputation: 40 910

Thank you Andrew for clarifying. I really appreciate your efforts to helping the Bitcoin community.

One thing i still need to get clarified "During that send, the account's balance is deducted by exactly the amount that was sent".

I suppose i have to use sendmany then, since i don't understand how the users accounts balance can be deducted by the exact amount when nothing specifies it to with SendToAddress, which uses default "" account?

Can you elobarote on the subtractFeeFrom parameter in sendmany? With sendmany you specify the receipient address, which pays the fee instead? – Peter Dalby 2018-05-16T18:25:36.613

also what if i leave the subtractFeeFrom parameter empty, will it then deduct from the amount specified instead, so the sender pays the fee? From rpc documentation it seems that "If no addresses are specified here, the sender pays the fee."Peter Dalby 2018-05-16T18:29:08.863

Last thing; how should i check what the account is actually able to maximumly use/spend, currently in the UI it's just based on the getBalance(account)

Should i in this case use listunspent and filter based on what is inside the account and the corresponding balance to then add them up?

or perhaps loop through all generated addresses, for example: listunspent 0 9999999 "[\"3QsuwHtXsWP8vLFZiGL2VK4MEf93YRuVkk\", etc, etc, etc]" – Peter Dalby 2018-05-16T18:36:18.690

Right, if you want to use accounts, you have to use sendmany or sendfrom. With sendmany, you specify the address(es) that the fee will be deducted from. Those addresses must be recipients and their outputs will have an equal amount subtracted in order to pay for transaction fees. If you do not specify subtractfeefrom, then the recipients will pay the full amount and the sender sends a little bit more to cover the transaction fees. What do you mean by "maximumly use/spend"? Again, the accounts and their balances are not tied to outputs (so listunspent is irrelevant).Andrew Chow 2018-05-16T18:47:29.993

Thanks. What i mean by maximumly use/spend is, based on an accounts receive and sending history that the amount which the account legitimately has as a final balance after all previous transactions are able to be sent out of the wallet. Perhaps this visual will explain it better: https://imgur.com/a/a3qnu5V

Peter Dalby 2018-05-16T19:29:09.167

So lets say i have a balance of 3BTC, sending half of it using: SendMany("hello@me.me", 3.........: 1.5, 1, "", [3...........], 0, 15)

Now half the balance of the account has been sent, and the fee will be paid by the receiving address (3...). Now listunspent and getBalance on the account should reflect that an input has been spent, and totally there is 1.5BTC left which can be sent out of the account in a new transaction, if they wish? :-) – Peter Dalby 2018-05-16T19:40:11.957

But then you say that accounts and their balances are not tied to outputs, so i guess it's impossible to show individual account balances like i want to based on the transaction movements?Peter Dalby 2018-05-16T19:49:34.160

You can't show individual account balances from the transaction history because accounts are not tied to outputs.Andrew Chow 2018-05-16T20:02:26.103

Would i be able to do that with a database table (every time an account sends a transaction) its logged to the database, then on wallet load the database is queried, the overall wallet balance is taken getBalance("") and then the amounts sent from the table are deducted from the balance to then match what the account is able to send? Or should i totally scrap anything related to sending transactions, as i heavily rely on individual user accounts.Peter Dalby 2018-05-16T20:07:13.123

Er perhaps rather than getBalance of the entire wallet then do getreceivedbyaddress with each account address/getreceivedbyaccount, and subtract the send amounts in the database from this total balance, to reflect what they're able to sendPeter Dalby 2018-05-16T20:26:08.303

Use getbalance <account> to get the balance of an account. If you have done everything correctly, this value should never be negative (which is actually a possibility) and should reflect how much each user actually has.Andrew Chow 2018-05-16T20:47:17.023

I deposit 1BTC, 0.5BTC, 1BTC, 0.5BTC into my account in individual transactions. I then send out 1.25BTC to an address using SendMany.

The account will be deducted 1.5BTC matching 2 inputs, and the change of 0.25BTC will be sent to a change address.

Doing getBalance(account) will then show 1.5BTC, which is incorrect, it should show 1.75BTC (included the change addr amount)

I suppose the only way to track the correct balance, is to track which inputs were available before the send, and which have been spent by the send? However this seems like a mess. Do you think it could work? – Peter Dalby 2018-05-17T05:45:31.670

For example:

Check inputs using listunspent.

You receive 3 BTC( 1, 0.5, 1, 0.5).


You send out 1.25BTC
.

Check balance, it should be 1.5BTC.

Check inputs again, look at the difference from earlier (2 inputs of 1.5BTC are gone now).

Add the amounts of the removed input (+=1.5BTC) to the balance of 1.5BTC and subtract the amount sent.



Balance should now be: 1.5+1.5-1.25 = 1.75BTC. – Peter Dalby 2018-05-17T06:02:57.667

But i don't even know if i can even manipulate the balance like that, only by using move? Seems like a bad idea overall... the confusion and frustration is real :-/ but maybe it might work?Peter Dalby 2018-05-17T06:06:58.533

Also sorry i mixed up inputs and outputs. I meant outputs (incoming transactions are outputs, used for inputs in send transaction) would it be possible to link them to accounts as such?Peter Dalby 2018-05-17T06:48:11.200

Lets say i dropped accounts and i link my account hello@peterdalby.me to be "" using SetAccount on the receiving addresses to "", i then use SendToAddress and subtract the fee. Would the "" account reflect the correct balance (including the change address amount)? This seem like the simpler "solution". I guess i should've never touched accounts to begin with... The typical uses at the bottom of this (https://en.bitcoin.it/wiki/Help:Accounts_explained) made it seem like it was possible to show individual account balances correctly.

Peter Dalby 2018-05-17T07:51:48.600

It seems like the only way to ensure that individual account balances will match what they expect after a send is to never send out more than the amount of 1 output received, to remove the change address amount. But the "" account should reflect the change address amount in it's balance, right?Peter Dalby 2018-05-17T08:00:03.270

I wonder how the bigger wallets such as Coinbase & Blockchain.info handle individual account balances. I suppose they use rawtransactions to specify the specific outputs to use for the transaction? And then have a massive internal accounting system to keep control of all the movements?Peter Dalby 2018-05-17T08:42:13.603

I think the best solution for me is to keep my hands of sending anything, and have individual user accounts export their private keys as strings or QR codes using dumpprivkey on receiving addresses, to then import to a third party wallet and send from there. I'm sad that it came to this, but again i really appreciate the time you have taken Andrew. Sorry for all my stupid ass questions. Understanding everything has been hard, to say the least.Peter Dalby 2018-05-17T12:09:23.750