Bitcoin Forum
April 25, 2024, 08:58:46 AM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: 1 2 [All]
  Print  
Author Topic: [PHP] Generate a sendmany with multiple outputs to the same address  (Read 4262 times)
SgtSpike (OP)
Legendary
*
Offline Offline

Activity: 1400
Merit: 1005



View Profile
October 03, 2012, 07:34:55 AM
 #1

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?
Even if you use Bitcoin through Tor, the way transactions are handled by the network makes anonymity difficult to achieve. Do not expect your transactions to be anonymous unless you really know what you're doing.
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1714035526
Hero Member
*
Offline Offline

Posts: 1714035526

View Profile Personal Message (Offline)

Ignore
1714035526
Reply with quote  #2

1714035526
Report to moderator
1714035526
Hero Member
*
Offline Offline

Posts: 1714035526

View Profile Personal Message (Offline)

Ignore
1714035526
Reply with quote  #2

1714035526
Report to moderator
1714035526
Hero Member
*
Offline Offline

Posts: 1714035526

View Profile Personal Message (Offline)

Ignore
1714035526
Reply with quote  #2

1714035526
Report to moderator
ingrownpocket
Legendary
*
Offline Offline

Activity: 952
Merit: 1000


View Profile
December 11, 2012, 11:58:14 AM
 #2

bump
gweedo
Legendary
*
Offline Offline

Activity: 1498
Merit: 1000


View Profile
December 11, 2012, 07:51:03 PM
 #3

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.
ingrownpocket
Legendary
*
Offline Offline

Activity: 952
Merit: 1000


View Profile
December 11, 2012, 08:07:11 PM
 #4

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.
gweedo
Legendary
*
Offline Offline

Activity: 1498
Merit: 1000


View Profile
December 11, 2012, 08:35:02 PM
 #5

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.
SgtSpike (OP)
Legendary
*
Offline Offline

Activity: 1400
Merit: 1005



View Profile
December 11, 2012, 08:38:29 PM
 #6

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.  Smiley

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.
ingrownpocket
Legendary
*
Offline Offline

Activity: 952
Merit: 1000


View Profile
December 11, 2012, 09:04:50 PM
 #7

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.  Smiley

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?
gweedo
Legendary
*
Offline Offline

Activity: 1498
Merit: 1000


View Profile
December 11, 2012, 09:05:55 PM
 #8

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.  Smiley

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.
SgtSpike (OP)
Legendary
*
Offline Offline

Activity: 1400
Merit: 1005



View Profile
December 11, 2012, 09:25:48 PM
 #9

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.  Smiley

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.
deepceleron
Legendary
*
Offline Offline

Activity: 1512
Merit: 1025



View Profile WWW
December 12, 2012, 04:41:30 AM
 #10

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.
SgtSpike (OP)
Legendary
*
Offline Offline

Activity: 1400
Merit: 1005



View Profile
December 12, 2012, 07:13:19 AM
 #11

How did this guy accomplish it when sending coins my way then?

http://blockchain.info/tx/67b9c10df1098152080baade7e3aab5cfa475ae154cf27000d1f000e370e65d2?show_adv=true
deepceleron
Legendary
*
Offline Offline

Activity: 1512
Merit: 1025



View Profile WWW
December 12, 2012, 08:32:02 AM
 #12


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
ingrownpocket
Legendary
*
Offline Offline

Activity: 952
Merit: 1000


View Profile
December 12, 2012, 08:32:14 AM
 #13


https://blockchain.info/tx/b62b5833e6c1f4c03c3a8aec43bde73c51ecf8be52a332ede720eae5788dbd64

I can do this using blockchain.info wallet.
SgtSpike (OP)
Legendary
*
Offline Offline

Activity: 1400
Merit: 1005



View Profile
December 12, 2012, 08:34:27 AM
 #14

So obviously, it is possible.  But deepceleron, you are saying the one sent to me wasn't a "normal" transaction, per say?
ingrownpocket
Legendary
*
Offline Offline

Activity: 952
Merit: 1000


View Profile
December 12, 2012, 08:37:39 AM
 #15

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
dooglus
Legendary
*
Offline Offline

Activity: 2940
Merit: 1330



View Profile
December 12, 2012, 06:54:09 PM
 #16


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

Just-Dice                 ██             
          ██████████         
      ██████████████████     
  ██████████████████████████ 
██████████████████████████████
██████████████████████████████
██████████████████████████████
██████████████████████████████
██████████████████████████████
██████████████████████████████
██████████████████████████████
██████████████████████████████
██████████████████████████████
    ██████████████████████   
        ██████████████       
            ██████           
   Play or Invest                 ██             
          ██████████         
      ██████████████████     
  ██████████████████████████ 
██████████████████████████████
██████████████████████████████
██████████████████████████████
██████████████████████████████
██████████████████████████████
██████████████████████████████
██████████████████████████████
██████████████████████████████
██████████████████████████████
    ██████████████████████   
        ██████████████       
            ██████           
   1% House Edge
kjj
Legendary
*
Offline Offline

Activity: 1302
Merit: 1024



View Profile
December 17, 2012, 01:21:41 AM
 #17

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.

17Np17BSrpnHCZ2pgtiMNnhjnsWJ2TMqq8
I routinely ignore posters with paid advertising in their sigs.  You should too.
Gavin Andresen
Legendary
*
Offline Offline

Activity: 1652
Merit: 2216


Chief Scientist


View Profile WWW
December 28, 2012, 09:09:11 PM
 #18

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).

How often do you get the chance to work on a potentially world-changing project?
SgtSpike (OP)
Legendary
*
Offline Offline

Activity: 1400
Merit: 1005



View Profile
December 28, 2012, 09:47:46 PM
 #19

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.  Wink

Why do you say "but please don't do that"?  Blockchain bloat?
piotr_n
Legendary
*
Offline Offline

Activity: 2053
Merit: 1354


aka tonikt


View Profile WWW
December 30, 2012, 05:20:43 PM
Last edit: December 30, 2012, 05:32:34 PM by piotr_n
 #20

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... Wink

Check out gocoin - my original project of full bitcoin node & cold wallet written in Go.
PGP fingerprint: AB9E A551 E262 A87A 13BB  9059 1BE7 B545 CDF3 FD0E
SgtSpike (OP)
Legendary
*
Offline Offline

Activity: 1400
Merit: 1005



View Profile
December 31, 2012, 04:30:22 PM
 #21

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... Wink
What was the workaround?
piotr_n
Legendary
*
Offline Offline

Activity: 2053
Merit: 1354


aka tonikt


View Profile WWW
December 31, 2012, 06:18:58 PM
 #22

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 .= '}\'';

Check out gocoin - my original project of full bitcoin node & cold wallet written in Go.
PGP fingerprint: AB9E A551 E262 A87A 13BB  9059 1BE7 B545 CDF3 FD0E
mrvision
Sr. Member
****
Offline Offline

Activity: 527
Merit: 250



View Profile
May 28, 2013, 03:35:55 PM
 #23


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
cmilian
Member
**
Offline Offline

Activity: 93
Merit: 10


View Profile
December 15, 2014, 04:14:15 PM
 #24

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?
Pages: 1 2 [All]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!