Author

Topic: Finding unspent transaction outputs (Read 4332 times)

hero member
Activity: 518
Merit: 505
September 03, 2014, 04:40:00 PM
#7
@barwizi you are missing a break; behind the mysqli line in non-standard type.
legendary
Activity: 882
Merit: 1000
September 01, 2014, 06:59:52 AM
#6
Code:
foreach ($tx["vout"] as $tx_out)

        {

          $scripttype=$tx_out["scriptPubKey"]["type"];

          switch ($scripttype)

          {

          case "pubkeyhash":

          case "pubkey":

          case "scripthash":

            $mysqli->query("insert into outputs (block_num, block_hash, transaction_hash, sequence, address, balance) values (".$i.", '".$block["hash"]."', '".$txid."', ".$tx_out["n"].", '".$tx_out["scriptPubKey"]["addresses"][0]."', ".$tx_out["value"].")");

            break;

          case "scriptPubKey":

          case "multisig":

            $mysqli->query("insert into outputs (block_num, block_hash, transaction_hash, sequence, address, balance) values (".$i.", '".$block["hash"]."', '".$txid."', ".$tx_out["n"].", '** ".$scripttype." **', ".$tx_out["value"].")");

            break;

          case "nonstandard":

            $mysqli->query("insert into outputs (block_num, block_hash, transaction_hash, sequence, address, balance) values (".$i.", '".$block["hash"]."', '".$txid."', ".$tx_out["n"].", '** ".$scripttype." **', ".$tx_out["value"].")");

          default:

            throw new Exception("don't know how to handle ".$scripttype." scripts in transaction ".$txid);

            continue;

It gives me this error

Code:
PHP Fatal error:  Uncaught exception 'Exception' with message 'don't know how to handle nonstandard scripts in transaction 521fdd0f3bd589de759af578cf6bfc595854ba578eb709fe7f7f42d43b2c7960' in /home/build/nrsbala/update-database.php:91
Stack trace:
#0 {main}
  thrown in /home/build/nrsbala/update-database.php on line 91


for this block :-

Code:
Array
(
    [hex] => 010000008b636053010000000000000000000000000000000000000000000000000000000000000000ffffffff0c02a25a0105062f503253482fffffffff010000000000000000000000000000
    [txid] => 521fdd0f3bd589de759af578cf6bfc595854ba578eb709fe7f7f42d43b2c7960
    [version] => 1
    [time] => 1398825867
    [locktime] => 0
    [vin] => Array
        (
            [0] => Array
                (
                    [coinbase] => 02a25a0105062f503253482f
                    [sequence] => 4294967295
                )

        )

    [vout] => Array
        (
            [0] => Array
                (
                    [value] => 0
                    [n] => 0
                    [scriptPubKey] => Array
                        (
                            [asm] =>
                            [hex] =>
                            [type] => nonstandard
                        )

                )

        )

    [blockhash] => 0fcc89dcc850cbf7d7149b8f1534b2464a7902991d19a9367dae0751b3a25be0
    [confirmations] => 46496
    [blocktime] => 1398825867
)

I need help figuring a way for these txs to be handled.
legendary
Activity: 882
Merit: 1000
September 01, 2014, 06:31:07 AM
#5
thanks for sharing. this script is both - unique and helpful.

i refined this for my needs, you might want to have a look at it.
https://github.com/vertoe/pts-unspent

 i copied vertoe's implementation however it seems to be choking on PoS blocks. Help!!!
sr. member
Activity: 412
Merit: 287
February 19, 2014, 06:39:28 PM
#4
Good job on the code! Should help people looking to play with transactions to p2sh addresses.
hero member
Activity: 518
Merit: 505
February 11, 2014, 09:32:56 PM
#3
thanks for sharing. this script is both - unique and helpful.

i refined this for my needs, you might want to have a look at it.
https://github.com/vertoe/pts-unspent
legendary
Activity: 2506
Merit: 1010
October 11, 2012, 11:52:21 AM
#2
the API just doesn't provide an easy way to get at it.

Nice.  This is an example of using raw transactions.

and won't tell me anything about transactions I'm not involved in.
Run bitcoin from get.  Use getrawtransaction with the decode flag.

Incidentally, raw transactions was just added with version 0.7 of the Bitcoin.org client, so that is a dependency.
 - http://en.bitcoin.it/wiki/Raw_Transactions
hero member
Activity: 651
Merit: 501
My PGP Key: 92C7689C
October 11, 2012, 10:21:49 AM
#1
I have a project in mind that would involve creating transactions on a webserver that would need to be handed off to a user for signing before they could be sent.  As I understand it, the inputs to any transaction are made up of unspent outputs from previous transactions.  Most wallet programs track the unspent outputs associated with your addresses, but they won't work with someone else's addresses.  You can find this information from blockexplorer.com or blockchain.info for any address, but they probably wouldn't appreciate hitting their servers every time someone needs a transaction generated.  Besides, if you have the Satoshi client running, all of the information is in your copy of the blockchain...the API just doesn't provide an easy way to get at it.

Yesterday, I knocked together some PHP that goes through the blockchain and builds up a table in a MySQL database with all unspent outputs.  It got through testnet pretty quickly.  It's still grinding away at the mainnet blockchain, but once you have it built, updates as new blocks are generated don't take long.  The database should be fairly small (currently at block 118650, and the database is ~27MB with ~144k entries), and finding unused outputs, totals at an address, or whatever is a SQL query away.  You need PHP built with Mysqli support, and you also need the client component from JSON-RPC PHP.

Code:
  require_once "jsonRPCClient.php";

  
$mysqli=new mysqli("""""""");
  if (
$mysqli->connect_errno)
    throw new 
Exception("database connection error");

  
$r=$mysqli->query("select max(block_num) from outputs"MYSQLI_USE_RESULT);
  
$w=$r->fetch_assoc();
  
$last_block_in_db=$w["max(block_num)"]+0;
  
$r->close();

  
$btc=new jsonRPCClient("http://:@localhost:8332");
  
$blocknum=$btc->getblockcount();

  if (
$last_block_in_db<$blocknum)
  {
    for (
$i=$last_block_in_db+1$i<=$blocknum$i++)
    {
      echo 
"block ".$i."\n";
      
$block=$btc->getblock($btc->getblockhash($i));
      foreach (
$block["tx"] as $txid)
      {
        
$tx=$btc->decoderawtransaction($btc->getrawtransaction($txid));
        foreach (
$tx["vin"] as $tx_in)
        {
          if (!
array_key_exists("coinbase"$tx_in))
            
$mysqli->query("delete from outputs where transaction_hash='".$tx_in["txid"]."' and sequence=".$tx_in["vout"].";");
        }
        foreach (
$tx["vout"] as $tx_out)
        {
          
$scripttype=$tx_out["scriptPubKey"]["type"];
          switch (
$scripttype)
          {
          case 
"pubkeyhash":
          case 
"pubkey":
          case 
"scripthash":
            
$mysqli->query("insert into outputs (block_num, block_hash, transaction_hash, sequence, address, balance) values (".$i.", '".$block["hash"]."', '".$txid."', ".$tx_out["n"].", '".$tx_out["scriptPubKey"]["addresses"][0]."', ".$tx_out["value"].")");
            break;
          case 
"nonstandard":
          case 
"multisig":
            
$mysqli->query("insert into outputs (block_num, block_hash, transaction_hash, sequence, address, balance) values (".$i.", '".$block["hash"]."', '".$txid."', ".$tx_out["n"].", '** ".$scripttype." **', ".$tx_out["value"].")");
            break;
          default:
            throw new 
Exception("don't know how to handle ".$scripttype." scripts in transaction ".$txid);
            break;
          }
        }
      }
    }
  }
  else
    echo 
"database is current\n";
?>


Substitute appropriate values for , , , , , and . has one table named outputs, defined as follows:

Code:
CREATE TABLE `outputs` (
  `block_num` int(11) NOT NULL,
  `block_hash` char(64) NOT NULL,
  `transaction_hash` char(64) NOT NULL,
  `sequence` int(11) NOT NULL,
  `address` varchar(34) NOT NULL,
  `balance` decimal(16,8) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1

With this, a user to your website can provide one or more addresses for payment.  You can generate a transaction (possibly with extra information embedded in the script) and hand it off to the user for signing.  Once signed, either the user or the website can send it to the blockchain.
Jump to: