Bitcoin Forum

Bitcoin => Bitcoin Technical Support => Topic started by: SgtSpike on October 03, 2012, 07:34:55 AM



Title: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: SgtSpike on October 03, 2012, 07:34:55 AM
I am utilizing the "Bitcoin Classes" by Mike Gogulski and theymos in some PHP code I am playing with.  As I understand it, the format for a sendmany is as follows:

$array[address[amount]]

Well, I can't send multiple times to the same address in the same sendmany in this format, since the address would be non-unique.  So, what would be the proper array format to sendmany to the same address multiple times?


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: ingrownpocket on December 11, 2012, 11:58:14 AM
bump


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: gweedo on December 11, 2012, 07:51:03 PM
Bitcoin classes doesn't have a sendtomany function, but if you want to do sendtomany with a jsonRPCClient then you just need an array that is setup like $array("address"=>amount); or $array['address']=amount;

Cause you it will have to be ran thru json_encode to get it to the correct format.


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: ingrownpocket on December 11, 2012, 08:07:11 PM
Bitcoin classes doesn't have a sendtomany function, but if you want to do sendtomany with a jsonRPCClient then you just need an array that is setup like $array("address"=>amount); or $array['address']=amount;

Cause you it will have to be ran thru json_encode to get it to the correct format.

I didn't realize he's using "Bitcoin Classes".
I'm using jsonRPCClient to connect with bitcoind.

I'm doing this:

$to=Array(
    "1address" => 1,
    "1address" => 2
);
sendmany("from", $to);

It will only send one payment to "1address".

The problem is that it has a duplicated key, so it's impossible to send multiple payments to the same address in the same transaction using this method.
blockchain.info allows us to do this, but I don't know how they do it.


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: gweedo on December 11, 2012, 08:35:02 PM
You might want to wrap the amounts in floatval(); Also you need to json_encode the array that is the issue you can't just pass the array.


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: SgtSpike on December 11, 2012, 08:38:29 PM
You might want to wrap the amounts in floatval(); Also you need to json_encode the array that is the issue you can't just pass the array.
floatval() wrapping is valuable advice, as I found.  :)

But the issue is that the array is organized in such a way as to use each address for the identifier of the element in the array.  You cannot use the same ID in the same array twice, thus eliminating the possibility of conducting a sendmany with multiple outputs to the same address with this particular PHP code.


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: ingrownpocket on December 11, 2012, 09:04:50 PM
You might want to wrap the amounts in floatval(); Also you need to json_encode the array that is the issue you can't just pass the array.
floatval() wrapping is valuable advice, as I found.  :)

But the issue is that the array is organized in such a way as to use each address for the identifier of the element in the array.  You cannot use the same ID in the same array twice, thus eliminating the possibility of conducting a sendmany with multiple outputs to the same address with this particular PHP code.

Exactly.
Is there any other way to do this?


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: gweedo on December 11, 2012, 09:05:55 PM
You might want to wrap the amounts in floatval(); Also you need to json_encode the array that is the issue you can't just pass the array.
floatval() wrapping is valuable advice, as I found.  :)

But the issue is that the array is organized in such a way as to use each address for the identifier of the element in the array.  You cannot use the same ID in the same array twice, thus eliminating the possibility of conducting a sendmany with multiple outputs to the same address with this particular PHP code.

Exactly.
Is there any other way to do this?

Yes after you build your array, do a search and combine the address into one.


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: SgtSpike on December 11, 2012, 09:25:48 PM
You might want to wrap the amounts in floatval(); Also you need to json_encode the array that is the issue you can't just pass the array.
floatval() wrapping is valuable advice, as I found.  :)

But the issue is that the array is organized in such a way as to use each address for the identifier of the element in the array.  You cannot use the same ID in the same array twice, thus eliminating the possibility of conducting a sendmany with multiple outputs to the same address with this particular PHP code.

Exactly.
Is there any other way to do this?

Yes after you build your array, do a search and combine the address into one.
The goal is to NOT combine the outputs to a single address into one.  I.e., you want to send multiple outputs to the same address at the same time.


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: deepceleron on December 12, 2012, 04:41:30 AM
Code:

  "out":[
    {
      "value":"1.00000000",
      "scriptPubKey":"OP_DUP OP_HASH160 ad4c20d5b1956015ea626f02afdaebe8ed17e1a8 OP_EQUALVERIFY OP_CHECKSIG"[/b]
    },
    {
      "value":"1.00000000",
      "scriptPubKey":"OP_DUP OP_HASH160 ad4c20d5b1956015ea626f02afdaebe8ed17e1a8 OP_EQUALVERIFY OP_CHECKSIG"[/b]
    }
  ]
}

Constructing a transaction like this is:

1. Either identical to sending the destination 2 BTC, in that clients consider the transaction to be adding 2BTC to the balance as one output (Bitcoin can't differentiate which output of these two might later have been spent, because they are identical with an identical transaction hash),

or

2. A good way to lose half your money because Bitcoin can't differentiate between which output of these two might later have been spent, because they are identical with an identical transaction hash.

https://en.bitcoin.it/wiki/BIP_0030
Quote
So far, the Bitcoin reference implementation always assumed duplicate transactions (transactions with the same identifier) didn't exist.


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: SgtSpike on December 12, 2012, 07:13:19 AM
How did this guy accomplish it when sending coins my way then?

http://blockchain.info/tx/67b9c10df1098152080baade7e3aab5cfa475ae154cf27000d1f000e370e65d2?show_adv=true


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: deepceleron on December 12, 2012, 08:32:02 AM
How did this guy accomplish it when sending coins my way then?

http://blockchain.info/tx/67b9c10df1098152080baade7e3aab5cfa475ae154cf27000d1f000e370e65d2?show_adv=true

TXOUT Amounts?
0.00100000
0.00100000
0.01000010
0.01001101
0.01001110
0.01100001
0.01100011
0.01100011
0.01100100
0.01100101
0.01100101
0.01100110
0.01101001
0.01101001
0.01101001
0.01101100
0.01101110
0.01110010
0.01110100
0.01110101
0.49730788
0.80211920

If you look at that address on blockexplorer (scroll to block 181957 at http://blockexplorer.com/address/18TKNbSLTrd3a2W8mtoH5uNzFhWRWNcuHU) you can see that it is freaked out, and considers the transaction to have been 0.9995 BTC, not 1.49680788.

It looks like the outputs are able to be spent by reference to the n index location of the output. Here is the spending transaction (although note a few outputs, index #4 & #14, for a total of .002 aren't spent here):
http://blockexplorer.com/rawtx/bf9d5f83dc9cc6d2876725abc90f0dba92d52a7146da6c7e5a10bbb154895b34


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: ingrownpocket on December 12, 2012, 08:32:14 AM
How did this guy accomplish it when sending coins my way then?

http://blockchain.info/tx/67b9c10df1098152080baade7e3aab5cfa475ae154cf27000d1f000e370e65d2?show_adv=true

https://blockchain.info/tx/b62b5833e6c1f4c03c3a8aec43bde73c51ecf8be52a332ede720eae5788dbd64 (https://blockchain.info/tx/b62b5833e6c1f4c03c3a8aec43bde73c51ecf8be52a332ede720eae5788dbd64)

I can do this using blockchain.info wallet.


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: SgtSpike on December 12, 2012, 08:34:27 AM
How did this guy accomplish it when sending coins my way then?

http://blockchain.info/tx/67b9c10df1098152080baade7e3aab5cfa475ae154cf27000d1f000e370e65d2?show_adv=true

https://blockchain.info/tx/b62b5833e6c1f4c03c3a8aec43bde73c51ecf8be52a332ede720eae5788dbd64 (https://blockchain.info/tx/b62b5833e6c1f4c03c3a8aec43bde73c51ecf8be52a332ede720eae5788dbd64)

I can do this using blockchain.info wallet.
So obviously, it is possible.  But deepceleron, you are saying the one sent to me wasn't a "normal" transaction, per say?


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: ingrownpocket on December 12, 2012, 08:37:39 AM
https://blockchain.info/tx/7cba3305f6a05dc6c663c272eacaaced3fa5f0ee56cc4cdca894b4ff0d03bdfe (https://blockchain.info/tx/7cba3305f6a05dc6c663c272eacaaced3fa5f0ee56cc4cdca894b4ff0d03bdfe)

I was trying to get around SatoshiDice max bet, but it doesn't seem possible.

http://satoshidice.com/full.php?tx=7cba3305f6a05dc6c663c272eacaaced3fa5f0ee56cc4cdca894b4ff0d03bdfe (http://satoshidice.com/full.php?tx=7cba3305f6a05dc6c663c272eacaaced3fa5f0ee56cc4cdca894b4ff0d03bdfe)


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: dooglus on December 12, 2012, 06:54:09 PM
https://blockchain.info/tx/7cba3305f6a05dc6c663c272eacaaced3fa5f0ee56cc4cdca894b4ff0d03bdfe (https://blockchain.info/tx/7cba3305f6a05dc6c663c272eacaaced3fa5f0ee56cc4cdca894b4ff0d03bdfe)

I was trying to get around SatoshiDice max bet, but it doesn't seem possible.

http://satoshidice.com/full.php?tx=7cba3305f6a05dc6c663c272eacaaced3fa5f0ee56cc4cdca894b4ff0d03bdfe (http://satoshidice.com/full.php?tx=7cba3305f6a05dc6c663c272eacaaced3fa5f0ee56cc4cdca894b4ff0d03bdfe)

Until around July you could get around their max bet limit using this technique.  Then they fixed it.

On 14th June you could bet the max as many times as you wanted.  The max was 5 BTC at this point:

http://www.satoshidice.com/lookup.php?tx=e6e65a1154e9cb74f90a5cc539b19c9acde4df9173d5ada457abb754f1e07e92

By 23rd July they had fixed the problem:

http://www.satoshidice.com/lookup.php?tx=400bea64815ce2035310f7caebdf5c3ce0ddd36bff11aece85ab20baa8b47496


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: kjj on December 17, 2012, 01:21:41 AM
Code:

  "out":[
    {
      "value":"1.00000000",
      "scriptPubKey":"OP_DUP OP_HASH160 ad4c20d5b1956015ea626f02afdaebe8ed17e1a8 OP_EQUALVERIFY OP_CHECKSIG"[/b]
    },
    {
      "value":"1.00000000",
      "scriptPubKey":"OP_DUP OP_HASH160 ad4c20d5b1956015ea626f02afdaebe8ed17e1a8 OP_EQUALVERIFY OP_CHECKSIG"[/b]
    }
  ]
}

Constructing a transaction like this is:

1. Either identical to sending the destination 2 BTC, in that clients consider the transaction to be adding 2BTC to the balance as one output (Bitcoin can't differentiate which output of these two might later have been spent, because they are identical with an identical transaction hash),

or

2. A good way to lose half your money because Bitcoin can't differentiate between which output of these two might later have been spent, because they are identical with an identical transaction hash.

https://en.bitcoin.it/wiki/BIP_0030
Quote
So far, the Bitcoin reference implementation always assumed duplicate transactions (transactions with the same identifier) didn't exist.


No, you are confusing transactions with outputs.  Transaction with duplicate hashes are no longer allowed, but duplicate outputs are.  The reason is that the transaction hash is the sole transaction identifier, while an output is identified by both the transaction hash and the output sequence number.  In this case, even though the transaction has two identical outputs, one is named <TxHash>.0 and the other is named <TxHash>.1.

In normal operation, the reference client hides the coin details from the user, and will present it to the user as a 2 BTC payment.  But behind the scenes, it knows that there are two outputs there and will act correctly, fully capable of redeeming and spending them one at a time.


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: Gavin Andresen on December 28, 2012, 09:09:11 PM
The bitcoind sendmany RPC call uses destination addresses as JSON Object keys, so you can't send to the same address multiple times in one transaction.

If you REALLY want to do that... first, why do you want to do that? I suppose if you want to use the blockchain as a messaging system then sending 0.123+0.567+etc might be an inefficient way of sending a message... but please don't do that.

Anyway, if you do REALLY want to do that, you'll have to write code to construct the transaction yourself. Then you could pass it to the signrawtransaction/sendrawtransaction RPC methods to broadcast it.  (you can't use createrawtransaction to create it, because it uses the same JSON syntax as sendmany for destination outputs).


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: SgtSpike on December 28, 2012, 09:47:46 PM
The bitcoind sendmany RPC call uses destination addresses as JSON Object keys, so you can't send to the same address multiple times in one transaction.

If you REALLY want to do that... first, why do you want to do that? I suppose if you want to use the blockchain as a messaging system then sending 0.123+0.567+etc might be an inefficient way of sending a message... but please don't do that.

Anyway, if you do REALLY want to do that, you'll have to write code to construct the transaction yourself. Then you could pass it to the signrawtransaction/sendrawtransaction RPC methods to broadcast it.  (you can't use createrawtransaction to create it, because it uses the same JSON syntax as sendmany for destination outputs).
Interesting, thanks for the response Gavin.  At the very least, blockchain.info has written the necessary code, and potentially, whoever it was that sent me a binary message earlier on in the year may have also programmed their own code for it.

At least this answers my question of whether it was a bitcoind issue or not.  Now I know that no bitcoind-based solution will accomplish this.  Perhaps time to learn the blockchain.info API, then.  ;)

Why do you say "but please don't do that"?  Blockchain bloat?


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: piotr_n on December 30, 2012, 05:20:43 PM
Yeah, it's a bummer that you cannot specify the same address twice - I once suffered from this as well, but a workaround was fairly simple, especially in PHP.

A bigger issue I've had with sendmany is that the command requires the "<fromaccount>" parameter and you cannot just say to it like "whatever account"...
So the way I use my client, having coins spread across several "accounts" (which I personally only use to label addresses), then it seems like someone had made this parameter mandatory just to piss me off... ;)


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: SgtSpike on December 31, 2012, 04:30:22 PM
Yeah, it's a bummer that you cannot specify the same address twice - I once suffered from this as well, but a workaround was fairly simple, especially in PHP.

A bigger issue I've had with sendmany is that the command requires the "<fromaccount>" parameter and you cannot just say to it like "whatever account"...
So the way I use my client, having coins spread across several "accounts" (which I personally only use to label addresses), then it seems like someone had made this parameter mandatory just to piss me off... ;)
What was the workaround?


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: piotr_n on December 31, 2012, 06:18:58 PM
What was the workaround?
Well, it's a workaround only if you're fine with single transaction per a recipient address (I was).
In such case, just sum up the amounts using a map with the destination address as the key.
Something like:
Code:
$addrs = array();
for(...) {
    $destaddr = ...
    $amount = ...
    if (array_key_exists($destaddr, $addrs)) {
        $addrs[$destaddr] += $amount;
    } else {
        $addrs[$destaddr] = $amount;
    }
}
After this you have only single addresses in $addrs (with the amounts summed up), so just:
Code:
$rpc = 'sendmany "'.ACCOUNT.'" \'{';
$com = false;
foreach(array_keys($addrs) as $da) {
$am = round($addrs[$da], 8);
if ($am>0) {
if ($com)  $rpc .= ', ';
$rpc .= '"'.$da.'":'.sprintf('%.8f',$am);
$com = true;
}
}
$rpc .= '}\'';


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: mrvision on May 28, 2013, 03:35:55 PM
How did this guy accomplish it when sending coins my way then?

http://blockchain.info/tx/67b9c10df1098152080baade7e3aab5cfa475ae154cf27000d1f000e370e65d2?show_adv=true

TXOUT Amounts?
0.00100000
0.00100000
0.01000010
0.01001101
0.01001110
0.01100001
0.01100011
0.01100011
0.01100100
0.01100101
0.01100101
0.01100110
0.01101001
0.01101001
0.01101001
0.01101100
0.01101110
0.01110010
0.01110100
0.01110101
0.49730788
0.80211920

It says "Nice Minecraft Build" xD


Title: Re: [PHP] Generate a sendmany with multiple outputs to the same address
Post by: cmilian on December 15, 2014, 04:14:15 PM
What was the workaround?
Well, it's a workaround only if you're fine with single transaction per a recipient address (I was).
In such case, just sum up the amounts using a map with the destination address as the key.
Something like:
Code:
$addrs = array();
for(...) {
    $destaddr = ...
    $amount = ...
    if (array_key_exists($destaddr, $addrs)) {
        $addrs[$destaddr] += $amount;
    } else {
        $addrs[$destaddr] = $amount;
    }
}
After this you have only single addresses in $addrs (with the amounts summed up), so just:
Code:
$rpc = 'sendmany "'.ACCOUNT.'" \'{';
$com = false;
foreach(array_keys($addrs) as $da) {
$am = round($addrs[$da], 8);
if ($am>0) {
if ($com)  $rpc .= ', ';
$rpc .= '"'.$da.'":'.sprintf('%.8f',$am);
$com = true;
}
}
$rpc .= '}\'';

This look like what i need. where did you add this code?