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