Author

Topic: sendmany vs sendtoaddress. Need advice from bitcoin developers. (Read 1396 times)

sr. member
Activity: 321
Merit: 250
good advice, thanks.  yes, I am testing everything very thoroughly with testnet and unit test framework before handling any real transactions.
legendary
Activity: 3472
Merit: 4801
I expect there will be a mix of large and small incoming transactions.

I like the createrawtransaction() idea.  The less black magic the better as far as I'm concerned.

Can you point me towards any code samples for using createrawtransaction()?



Depending on how complex your needs are, you might end up finding that you need more control over things than the tools you are using provide.  You can use listunspent to get a list of unspent outputs and build your own raw transaction using createrawtransaction by choosing which of those outputs you want to use as inputs.  This would give you complete control over the fee and size of the transaction as well.

How many inputs there will be is going to depend a lot on how the wallet that you are spending from is funded.  If you send one large value transaction to the wallet, and keep spending that balance until it is practically gone, then you'll always have just one input.  If you have users continuously sending smaller transactions to the wallet that you are recycling to create outgoing transactions, then it will be difficult to predict the size of the transaction if you aren't creating raw transactions.

I don't have any code samples available at the moment.  Hopefully someone else will stop by with some.

Be forewarned, when using createrawtransaction, it is very easy to forget to send excess value back into the wallet with a "change" output.  Failure to do so can result in unintentionally paying a very happy miner (or pool) a very large fee.  Some experienced and knowledgeable developers here who knew exactly what they were doing have made this very mistake.  You should probably try out your code on testnet, and perhaps have someone else knowledgeable review it for you to make sure you haven't accidentally done something unintentional before you try running it on the bitcoin network.
sr. member
Activity: 321
Merit: 250
I expect there will be a mix of large and small incoming transactions.

I like the createrawtransaction() idea.  The less black magic the better as far as I'm concerned.

Can you point me towards any code samples for using createrawtransaction()?



Depending on how complex your needs are, you might end up finding that you need more control over things than the tools you are using provide.  You can use listunspent to get a list of unspent outputs and build your own raw transaction using createrawtransaction by choosing which of those outputs you want to use as inputs.  This would give you complete control over the fee and size of the transaction as well.

How many inputs there will be is going to depend a lot on how the wallet that you are spending from is funded.  If you send one large value transaction to the wallet, and keep spending that balance until it is practically gone, then you'll always have just one input.  If you have users continuously sending smaller transactions to the wallet that you are recycling to create outgoing transactions, then it will be difficult to predict the size of the transaction if you aren't creating raw transactions.
legendary
Activity: 3472
Merit: 4801
Good info Danny, thanks.  A follow-on question then would be:  how can I know how many inputs there are?   I know the number of outputs, but doesn't bitcoind figure out all the inputs internally?

  * Is there such a thing as too many outputs in one sendmany transaction?
  * Is there an optimal number of outputs?

Yes, but its a pretty large number.  It will depend a bit on how many inputs are being used in your transaction, but there is a maximum transaction size.  Inputs tend to be approximately 180 bytes, outputs tend to bee approximately 40 bytes.  There are some additional bytes for overhead in the transaction (transactionID, input_qty, output_qty, etc).  A safe assumption would be 50 bytes of overhead.  If you keep your transaction size below 10 kilobytes, you'll probably reduce transaction fees.  Any transaction larger than that will incur a "per kilobyte" fee.


Depending on how complex your needs are, you might end up finding that you need more control over things than the tools you are using provide.  You can use listunspent to get a list of unspent outputs and build your own raw transaction using createrawtransaction by choosing which of those outputs you want to use as inputs.  This would give you complete control over the fee and size of the transaction as well.

How many inputs there will be is going to depend a lot on how the wallet that you are spending from is funded.  If you send one large value transaction to the wallet, and keep spending that balance until it is practically gone, then you'll always have just one input.  If you have users continuously sending smaller transactions to the wallet that you are recycling to create outgoing transactions, then it will be difficult to predict the size of the transaction if you aren't creating raw transactions.
sr. member
Activity: 321
Merit: 250
hmm, not sure I understand.

I would use getnewaddress() when creating a local address for receiving.  What I am wanting to do though is query transactions that I have sent to a 3rd party address, eg:

I'm not sure about your main questions, but in answer to your PS: Each time you use getnewaddress immeadiately use setaccount to create an account with the same name as the address, which contains only that address.  Then you can use listtransactions and sendfrom and specify the account/address.

Hope that helps
sr. member
Activity: 321
Merit: 250
Good info Danny, thanks.  A follow-on question then would be:  how can I know how many inputs there are?   I know the number of outputs, but doesn't bitcoind figure out all the inputs internally?

  * Is there such a thing as too many outputs in one sendmany transaction?
  * Is there an optimal number of outputs?

Yes, but its a pretty large number.  It will depend a bit on how many inputs are being used in your transaction, but there is a maximum transaction size.  Inputs tend to be approximately 180 bytes, outputs tend to bee approximately 40 bytes.  There are some additional bytes for overhead in the transaction (transactionID, input_qty, output_qty, etc).  A safe assumption would be 50 bytes of overhead.  If you keep your transaction size below 10 kilobytes, you'll probably reduce transaction fees.  Any transaction larger than that will incur a "per kilobyte" fee.

legendary
Activity: 3472
Merit: 4801
  * Is there such a thing as too many outputs in one sendmany transaction?
  * Is there an optimal number of outputs?

Yes, but its a pretty large number.  It will depend a bit on how many inputs are being used in your transaction, but there is a maximum transaction size.  Inputs tend to be approximately 180 bytes, outputs tend to bee approximately 40 bytes.  There are some additional bytes for overhead in the transaction (transactionID, input_qty, output_qty, etc).  A safe assumption would be 50 bytes of overhead.  If you keep your transaction size below 10 kilobytes, you'll probably reduce transaction fees.  Any transaction larger than that will incur a "per kilobyte" fee.
newbie
Activity: 15
Merit: 0
I'm not sure about your main questions, but in answer to your PS: Each time you use getnewaddress immeadiately use setaccount to create an account with the same name as the address, which contains only that address.  Then you can use listtransactions and sendfrom and specify the account/address.

Hope that helps
sr. member
Activity: 321
Merit: 250
anyone?

Perhaps someone that is not a newbie can take pity and bring this question to the attention of a developer?
sr. member
Activity: 321
Merit: 250
Hi, I would like to understand better the differences between using sendtoaddress and sendmany, from both the perspective of the sender and the receiver, and in particular in regards to fees and confirmation time.

Background:

I am working on an app that will be sending bitcoins sporadically.  I'm sure it will start off with a low volume -- perhaps 1 send a minute or even per hour, but could eventually achieve a high volume. I am attempting to ensure it can handle a high transaction volume, say 2 sends/sec on average, or even greater.

It is important that funds get sent right away.  Well, a one minute delay might be ok to batch multiple sends together, but 25 minutes like many mining pools are doing would not be very ideal at all from the perspective of my customers.  And also that would be a very big transaction if we are talking 2+ sends/sec that have been batched together for 25 mins. ( I guess that could be dealt with by sending after N sends are requested instead of waiting a fixed time period, but then what is the optimal value for N? )

My initial (naive?) implementation (untested as of yet) was just to have a queue of outgoing send requests, which I process oldest first, and send using sendtoaddress().  After all are processed, my code sleeps 1/4 second and checks the queue again.  This is conceptually very straightforward and nice.

In reading the docs for sendtoaddress() I came across sendmany() and googled for it a lot, searched this forum, etc.  I have not found any specifics on when to use it instead of sendtoaddress().   I have the vague notion that it should help cut down on fees some if multiple outputs are combined together in a single transaction, but no specifics.  For example, I ask:

  * Are there any guidelines for when sendmany is cheaper or faster than sendtoaddress()?
  *      and can that be calculated?
  * Is there such a thing as too many outputs in one sendmany transaction?
  * Is there an optimal number of outputs?
  * Is there some other way to determine "optimal" time to send, or which sends to group together?
  * how can one compute the optimal fee to use with both sendmany() and sendtoaddress()?
 
I appreciate any and all advice on these topics.


PS: One other thing I noticed is that there does not seem to be any API in bitcoind to query for sent payments by recipient address, eg:  listtransactionsbyaddress(address, category=send)  I wanted to do this as a sanity check to make sure I am not sending the same order multiple times, eg if a rollback occurs in my DB after I sent payment but before it was recorded in DB.  I was able to do a hack calling listtransactions('*', 1000) for the past 1000, and iterating through, but it is very kludgy.  I think that instead I will probably keep a local logfile of sends outside the DB that I can check.







Jump to: