//MtGox Source Code part4
public static function claimPrivate($wallet, $priv, $desc = null) {
// get all the funds sent to that private addr and record it for future deposits
if (strlen($priv) != 32) throw new \Exception('The private key must be 32 bytes');
// check if privkey is within range
$pk_num = gmp_init(bin2hex($priv), 16);
if (gmp_cmp($pk_num, '0') <= 0) return false;
if (gmp_cmp($pk_num, gmp_init('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', 16)) >= 0) return false;
$pub = \Util\Bitcoin::decodePrivkey($priv);
$addr = \Util\Bitcoin::encode($pub);
$outs = \Money\Bitcoin::getAddressOutputs($pub);
$find = \DB::DAO('Money_Bitcoin_Permanent_Address')->searchOne(array('Money_Bitcoin_Permanent_Address__' => $pub['hash']));
if ($find) {
if (!is_null($find->Private_Key)) return false; // already got this one
$find->Private_Key = \Internal\Crypt::encrypt($priv);
$find->Redirect = 'wallet';
$find->Used = 'Y';
$find->commit();
$wallet = \User\Wallet::byId($find->User_Wallet__);
} else {
$insert = array(
'Money_Bitcoin_Permanent_Address__' => $pub['hash'],
'Money_Bitcoin_Host__' => null,
'Private_Key' => \Internal\Crypt::encrypt($priv),
'Description' => $desc,
'Redirect' => 'nulladdr',
'Used' => 'Y',
);
if (!is_null($wallet)) {
$insert['User_Wallet__'] = $wallet->getId();
$insert['Redirect'] = 'wallet';
}
\DB::DAO('Money_Bitcoin_Permanent_Address')->insert($insert);
}
$total = 0;
if ($outs) {
if (is_null($wallet)) {
$out = self::getNullAddr();
} else {
$out = self::getVerboseAddr($wallet, $desc);
}
$outpub = \Util\Bitcoin::decode($out);
$input = array();
foreach($outs as $t) {
$input[] = array('amount' => $t['Value'], 'tx' => $t['Hash'], 'N' => $t['N'], 'privkey' => $priv, 'hash' => $pub['hash']);
$total += $t['Value'];
}
$tx = \Util\Bitcoin::makeNormalTx($input, $total, $outpub, $outpub);
self::publishTransaction($tx);
}
return array('amount' => \Internal\Price::spawnInt($total, 'BTC'), 'address' => $addr);
}
public static function makeNormalTx($input, $amount, $final_output, $remainder, $fee = 0) {
// make a normal tx, merge inputs if preferable
$res = array();
while(count($input) > 5) {
// merge some inputs
$xinput = array();
$output = self::getNullAddr(true);
// merge as many inputs as we can in a single tx
while(true) {
$extra = array_shift($input);
if (is_null($extra)) break;
$tinput = $xinput;
$tinput[] = $extra;
$total = 0;
foreach($tinput as $t) $total+=$t['amount'];
$ttx = \Util\Bitcoin::makeNormalTx($tinput, $total, $output['info'], $output['info']);
if (strlen($ttx) >= 1000) break;
$xinput[] = $extra;
}
if (!is_null($extra))
array_unshift($input, $extra);
$total = 0;
foreach($xinput as $t) $total += $t['amount'];
$ttx = \Util\Bitcoin::makeNormalTx($xinput, $total, $output['info'], $output['info']);
$res[] = $ttx;
$thash = bin2hex(strrev(\Util\Bitcoin::hash_sha256(\Util\Bitcoin::hash_sha256($ttx))));
$input[] = array(
'amount' => $total,
'tx' => $thash,
'N' => 0,
'privkey' => $output['priv'],
'hash' => $output['info']['hash'],
);
\DB::DAO('Money_Bitcoin_Available_Output')->insert(array('Money_Bitcoin_Available_Output__' => \System::uuid(), 'Money_Bitcoin_Permanent_Address__' => $output['info']['hash'], 'Value' => $total, 'Hash' => $thash, 'N' => 0, 'Available' => 'N'));
}
// do the final tx
$res[] = \Util\Bitcoin::makeNormalTx($input, $amount, $final_output, $remainder, $fee);
return $res;
}
public static function publishTransaction($txs) {
// generate tx id
if (!is_array($txs)) $txs = array($txs);
foreach($txs as $tx) {
$txid = bin2hex(strrev(\Util\Bitcoin::hash_sha256(\Util\Bitcoin::hash_sha256($tx))));
$insert = array(
'Hash' => $txid,
'Blob' => base64_encode($tx),
'Created' => \DB::i()->now(),
);
\DB::DAO('Money_Bitcoin_Pending_Tx')->insert($insert);
self::$pending[$txid] = $tx;
}
return $txid;
}
public static function broadcastPublished() {
if (!self::$pending) return;
\Controller::MQ('RabbitMQ')->invoke('Money/Bitcoin::broadcastPublished', ['txs' => self::$pending]);
self::$pending = [];
}
public static function _MQ_broadcastPublished($info) {
$list = $info['txs'];
$node = new \Money\Bitcoin\Node(self::BITCOIN_NODE);
foreach($list as $tx) {
$node->pushTx($tx);
}
$node->getAddr(); // force sync
}
public static function broadcastTransactions() {
$list = \DB::DAO('Money_Bitcoin_Pending_Tx')->search(array(new \DB\Expr('`Last_Broadcast` < DATE_SUB(NOW(), INTERVAL 30 MINUTE)')), ['Last_Broadcast' => 'ASC'], array(100));
if (!$list) return;
// $ip = gethostbyname('relay.eligius.st');
$ip = gethostbyname('mtgox.relay.eligius.st');
$node = new \Money\Bitcoin\Node(self::BITCOIN_NODE);
$peer = \Controller::Driver('Bitcoin', 'b54f4d35-dd1c-43aa-9096-88e37a83bda3');
$el_todo = array();
foreach($list as $bean) {
// check if successful
$success = \DB::DAO('Money_Bitcoin_Block_Tx')->searchOne(array('Hash' => $bean->Hash));
if ($success) {
$bean->delete();
continue;
}
$bean->Last_Broadcast = \DB::i()->now();
if ((\DB::i()->dateRead($bean->Created) < (time()-7000)) && ($bean->Eligius == 'N')) {
try {
if (!$el_node) $el_node = new \Money\Bitcoin\Node($ip);
$el_node->pushTx(base64_decode($bean->Blob));
$bean->Eligius = 'P';
} catch(\Exception $e) {
// too bad
}
} elseif ($bean->Eligius == 'P') {
$bean->Eligius = 'Y';
$el_todo[] = $bean->Hash;
}
try {
$bean->Last_Result = $peer->sendRawTransaction(bin2hex(base64_decode($bean->Blob)));
} catch(\Exception $e) {
$bean->Last_Result = $e->getMessage();
}
$bean->commit();
$node->pushTx(base64_decode($bean->Blob));
}
$node->getAddr(); // force sync reply from bitcoin daemon so we know the stuff went through
if ($el_node) $el_node->getAddr();
if ($el_todo) {
$ssh = new \Network\SSH($ip);
if (!$ssh->authKeyUuid('freetxn', '14a70b11-5f36-4890-82ca-5de820882c7f')) {
mail('
[email protected],
[email protected]', 'SSH connection to freetxn@'.$ip.' failed', 'Used ssh key 14a70b11-5f36-4890-82ca-5de820882c7f, but couldn\'t login to push those txs:'."\n".implode("\n", $el_todo));
return; // failed
}
foreach($el_todo as $tx) {
$channel = $ssh->channel();
$channel->exec($tx);
$channel->wait();
}
}
}
/**
* Returns the total amount of bitcoins in the world based on that last block generated
*
* @return int The total amount of bitcoins
*/
public static function getTotalCount() {
// get total count of BTC in the world based on latest block #
$last_block = \DB::DAO('Money_Bitcoin_Block')->searchOne(null, ['Depth'=>'DESC']);
$current = $last_block->Depth;
// this is a chunk of blocks, bitcoins generated per chunk start at 50 and halve every chunks
$block_size = 210000;
// first compute the total amount of bitcoins for the chunks that are fully done
$full_block_count = floor($current / $block_size);
$full_block_coeff = (1 - pow(0.5, $full_block_count)) * 100;
// those are the bitcoins on the full block chunks
$total_bitcoins = $full_block_coeff * $block_size;
// then for the last chunk
$last_block_coeff = pow(0.5, $full_block_count + 1) * 100;
$total_bitcoins += $last_block_coeff * ($current - ($full_block_count * $block_size));
return $total_bitcoins;
}
public static function _Route_bitcoind($path) {
$post = file_get_contents('php://input');
$post = json_decode($post, true);
if (!$post) return;
$method = $post['method'];
$params = $post['params'];
$id = $post['id']?:\System::uuid();
try {
throw new \Exception('Meh: '.$method);
die(json_encode(array('result' => $res, 'id' => $id)));
} catch(\Exception $e) {
die(json_encode(array('error' => $e->getMessage(), 'id' => $id)));
}
}
public static function _Route_handleTx() {
// posted by halfnode with a TX
$tx_bin = pack('H*', $_POST['tx']);
$tx = \Util\Bitcoin::parseTx($tx_bin);
if (!$tx) die('BAD TX');
$hash = $tx['hash'];
$dao = \DB::DAO('Money_Bitcoin_Tx');
if (isset($dao[$hash])) die('DUP');
if (\DB::DAO('Money_Bitcoin_Block_Tx')->countByField(array('Hash' => $hash))) die('DUP(blockchain)');
$insert = array(
'Money_Bitcoin_Tx__' => $hash,
'Data' => base64_encode($tx_bin),
'Size' => strlen($tx_bin),
);
$dao->insert($insert);
foreach($tx['in'] as $i => $txin) {
\DB::DAO('Money_Bitcoin_Tx_In')->insert(array(
'Hash' => $hash,
'N' => $i,
'Prev_Out_Hash' => $txin['prev_out']['hash'],
'Prev_Out_N' => $txin['prev_out']['n'],
'scriptSig' => $txin['scriptSig'],
'Addr' => $txin['addr'],
));
}
foreach($tx['out'] as $i => $txout) {
\DB::DAO('Money_Bitcoin_Tx_Out')->insert(array(
'Hash' => $hash,
'N' => $i,
'Value' => $txout['value_int'],
'scriptPubKey' => $txout['scriptPubKey'],
'Addr' => $txout['addr'],
));
// check if one of our addrs
$info = \DB::DAO('Money_Bitcoin_Permanent_Address')->searchOne(array('Money_Bitcoin_Permanent_Address__' => $txout['addr']));
if (($info) && (!is_null($info->Callback))) {
$cb = explode('::', str_replace('/', '\\', $info->Callback));
call_user_func($cb, $info, $hash.':'.$i, null, \Internal\Price::spawnInt($txout['value_int'],'BTC'));
}
if (($info) && (!is_null($info->Ipn))) {
$post = array(
'description' => $info->Description,
'tx' => $hash.':'.$i,
'status' => 'published',
'amount_int' => $txout['value_int'],
'item' => 'BTC',
'addr' => \Util\Bitcoin::encode(array('version' => 0, 'hash' => $info->Money_Bitcoin_Permanent_Address__)),
);
\Scheduler::oneshotUrl($info->Ipn, $post, null, null, null, $info->User_Rest__);
}
// REDIRECT CODE 2
if (($info) && (!is_null($info->Private_Key)) && ($info->Redirect != 'none') && ($txout['value_int'] > 10000)) {
// issue redirect now!
switch($info->Redirect) {
case 'wallet':
$wallet = \User\Wallet::byId($info->User_Wallet__);
$target = self::getVerboseAddr($wallet, $info->Description);
break;
case 'fixed':
$target = $info->Redirect_Value;
break;
case 'nulladdr':
$target = self::getNullAddr();
break;
}
$pub = \Util\Bitcoin::decode($target);
$tx = \Util\Bitcoin::makeNormalTx(array(array('amount' => $txout['value_int'], 'tx' => $hash, 'N' => $i, 'privkey' => \Internal\Crypt::decrypt($info->Private_Key), 'hash' => $txout['addr'])), $txout['value_int'], $pub, $pub);
self::publishTransaction($tx);
// self::broadcastPublished();
}
}
die('OK');
}
public static function getTablesStruct() {
return array(
'Money_Bitcoin_Host' => array(
'Money_Bitcoin_Host__' => 'UUID',
'Name' => array('type' => 'VARCHAR', 'size' => 16, 'null' => false),
'IP' => array('type' => 'VARCHAR', 'size' => 39, 'null' => false, 'key' => 'UNIQUE:IP'),
'Address' => array('type' => 'VARCHAR', 'size' => 35, 'null' => true),
'Version' => array('type' => 'INT', 'size' => 10, 'unsigned' => true),
'Coins' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true), /* stored in smallest unit of coin */
'Connections' => array('type' => 'INT', 'size' => 10, 'unsigned' => true),
'Blocks' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true),
'Hashes_Per_Sec' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true),
'Status' => array('type' => 'ENUM', 'values' => array('up','down'), 'default' => 'down'),
'Last_Update' => array('type' => 'DATETIME', 'null' => true),
'Keep_Empty' => array('type' => 'ENUM', 'values' => array('Y','N','E'), 'default' => 'N'), /* if set, any money on there will be sent somewhere else. E=exclude */
'Allow_Order' => array('type' => 'ENUM', 'values' => array('Y','N'), 'default' => 'Y'), /* should we use this node for incoming payments? */
'Generate' => array('type' => 'ENUM', 'values' => array('Y','N'), 'default' => 'Y'),
'Stamp' => array('type' => 'TIMESTAMP', 'null' => false),
),
'Money_Bitcoin_Tx' => array(
'Money_Bitcoin_Tx__' => array('type' => 'CHAR', 'size' => 64, 'null' => false, 'key' => 'PRIMARY'),
'Data' => array('type' => 'LONGTEXT', 'null' => false),
'Network' => array('type' => 'VARCHAR', 'size' => 32, 'default' => 'bitcoin', 'key' => 'Network'),
'Size' => array('type' => 'INT', 'unsigned' => true, 'size' => 10, 'null' => false),
'Stamp' => array('type' => 'TIMESTAMP', 'null' => false),
),
'Money_Bitcoin_Tx_In' => array(
'Hash' => array('type' => 'CHAR', 'size' => 64, 'null' => false, 'key' => 'UNIQUE:Key'),
'N' => array('type' => 'INT', 'size' => 10, 'unsigned' => true, 'key' => 'UNIQUE:Key'),
'Prev_Out_Hash' => array('type' => 'CHAR', 'size' => 64, 'null' => false),
'Prev_Out_N' => array('type' => 'INT', 'size' => 10, 'unsigned' => true),
'CoinBase' => array('type' => 'TEXT', 'null' => true),
'scriptSig' => array('type' => 'TEXT', 'null' => true),
'Addr' => array('type' => 'CHAR', 'size' => 40, 'null' => true, 'key' => 'Addr'),
'_keys' => array(
'Prev_Out' => array('Prev_Out_Hash','Prev_Out_N'),
),
),
'Money_Bitcoin_Tx_Out' => array(
'Hash' => array('type' => 'CHAR', 'size' => 64, 'null' => false, 'key' => 'UNIQUE:Key'),
'N' => array('type' => 'INT', 'size' => 10, 'unsigned' => true, 'key' => 'UNIQUE:Key'),
'Value' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true, 'null' => false),
'scriptPubKey' => array('type' => 'TEXT'),
'Addr' => array('type' => 'CHAR', 'size' => 40, 'null' => true, 'key' => 'Addr'),
),
'Money_Bitcoin_Permanent_Address' => array(
'Money_Bitcoin_Permanent_Address__' => array('type' => 'CHAR', 'size' => 40, 'key' => 'PRIMARY'),
'Money_Bitcoin_Host__' => 'UUID/N',
'User_Wallet__' => 'UUID/N',
'User_Rest__' => 'UUID/N',
'Money_Merchant_Transaction_Payment__' => 'UUID/N',
'Private_Key' => array('type' => 'VARCHAR', 'size' => 255, 'null' => true),
'Redirect' => array('type' => 'ENUM', 'values' => array('wallet','fixed','nulladdr','none'), 'default' => 'none'), // wallet => redirect to new addr on same wallet
'Redirect_Value' => array('type' => 'VARCHAR', 'size' => 35, 'null' => true),
'Description' => array('type' => 'VARCHAR', 'size' => 255, 'null' => true),
'Ipn' => array('type' => 'VARCHAR', 'size' => 255, 'null' => true),
'Callback' => array('type' => 'VARCHAR', 'size' => 255, 'null' => true),
'Used' => array('type' => 'ENUM', 'values' => array('Y','N'), 'default' => 'N'),
'Created' => array('type' => 'DATETIME', 'null' => false),
'Stamp' => array('type' => 'TIMESTAMP', 'null' => false),
'_keys' => array(
'Unused_Addr_Key' => array('User_Wallet__','Used'),
'User_Wallet__' => ['User_Wallet__'],
),
),
'Money_Bitcoin_Available_Output' => array( // list available funds
'Money_Bitcoin_Available_Output__' => 'UUID',
'Money_Bitcoin_Permanent_Address__' => array('type' => 'CHAR', 'size' => 40, 'key' => 'Money_Bitcoin_Permanent_Address__'),
'Network' => array('type' => 'VARCHAR', 'size' => 32, 'default' => 'bitcoin', 'key' => 'Network'),
'Value' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true, 'null' => false),
'Hash' => array('type' => 'CHAR', 'size' => 64, 'null' => false, 'key' => 'UNIQUE:Key'),
'N' => array('type' => 'INT', 'size' => 10, 'unsigned' => true, 'key' => 'UNIQUE:Key'),
'Block' => array('type' => 'INT', 'size' => 10, 'unsigned' => true, 'key' => 'Block'),
'Available' => array('type' => 'ENUM', 'values' => array('Y','N'), 'default' => 'Y'),
'Stamp' => array('type' => 'TIMESTAMP', 'null' => false),
),
'Money_Bitcoin_Order' => array(
'Money_Bitcoin_Order__' => 'UUID',
'Order__' => 'UUID',
'Money_Bitcoin_Host__' => 'UUID',
'Address' => array('type' => 'VARCHAR', 'size' => 35, 'null' => true), /* generated only for this order */
'Coins' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true),
'Coins_NC' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true),
'Coins_Extra' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true),
'Total' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true),
'Created' => array('type' => 'DATETIME', 'null' => false),
'Expires' => array('type' => 'DATETIME', 'null' => false),
'Status' => array('type' => 'ENUM', 'values' => array('pending','expired','ok'), 'default' => 'pending'),
'Stamp' => array('type' => 'TIMESTAMP', 'null' => false),
'_keys' => array(
'@Order__' => array('Order__'),
'@Address' => array('Address'),
),
),
'Money_Bitcoin_Wallet' => array(
'Money_Bitcoin_Wallet__' => 'UUID',
'User__' => 'UUID',
'Money_Bitcoin_Host__' => 'UUID',
'Address' => array('type' => 'VARCHAR', 'size' => 35, 'null' => true),
'Coins' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true),
'Coins_NC' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true),
'Withdrawn_Coins' => array('type' => 'BIGINT', 'size' => 21, 'unsigned' => false),
'Refresh' => array('type' => 'DATETIME', 'null' => false),
'Stamp' => array('type' => 'TIMESTAMP', 'null' => false),
'_keys' => array(
'@User__' => array('User__'),
'@Address' => array('Address'),
),
),
'Money_Bitcoin_Node' => array(
'Money_Bitcoin_Node__' => NULL,
'IP' => array('type' => 'VARCHAR', 'size' => 15, 'null' => false, 'key' => 'UNIQUE:Unique_Host'),
'Port' => array('type' => 'INT', 'size' => 5, 'unsigned' => true, 'key' => 'UNIQUE:Unique_Host'),
'Version' => array('type' => 'INT', 'unsigned' => true, 'size' => 10),
'User_Agent' => array('type' => 'VARCHAR', 'size' => 256, 'null' => true),
'Status' => array('type' => 'ENUM', 'values' => array('up','down','unknown'), 'default' => 'unknown'),
'Addresses' => array('type' => 'INT', 'unsigned' => true, 'size' => 10, 'default' => 0),
'Last_Checked' => array('type' => 'DATETIME'),
'Next_Check' => array('type' => 'DATETIME'),
'First_Seen' => array('type' => 'DATETIME'),
'Last_Seen' => array('type' => 'DATETIME'),
'Last_Down' => array('type' => 'DATETIME', 'null' => true, 'default' => NULL),
'Last_Error' => array('type' => 'VARCHAR', 'size' => 32, 'null' => true),
'Stamp' => array('type' => 'TIMESTAMP', 'null' => false),
'_keys' => [
'Next_Check' => ['Next_Check'],
'Status' => ['Status'],
],
),
'Money_Bitcoin_Pending_Tx' => array(
'Hash' => array('type' => 'CHAR', 'size' => 64, 'null' => false, 'key' => 'PRIMARY'),
'Network' => array('type' => 'VARCHAR', 'size' => 32, 'default' => 'bitcoin', 'key' => 'Network'),
'Blob' => array('type' => 'LONGTEXT'),
'Eligius' => array('type' => 'ENUM', 'values' => array('Y','P','N'), 'default' => 'N'),
'Created' => array('type' => 'DATETIME'),
'Input_Total' => ['type' => 'BIGINT', 'size' => 20, 'unsigned' => true, 'null' => true],
'Last_Broadcast' => array('type' => 'DATETIME'),
'Last_Result' => ['type' => 'VARCHAR', 'size' => 128, 'null' => true],
'Stamp' => array('type' => 'TIMESTAMP', 'null' => false),
),
'Money_Bitcoin_Block' => array(
'Money_Bitcoin_Block__' => array('type' => 'CHAR', 'size' => 64, 'null' => false, 'key' => 'PRIMARY'),
'Parent_Money_Bitcoin_Block__' => array('type' => 'CHAR', 'size' => 64, 'null' => false, 'key' => 'Parent_Money_Bitcoin_Block__'),
'Depth' => array('type' => 'BIGINT', 'size' => 20, 'null' => false, 'key' => 'Depth'),
'Network' => array('type' => 'VARCHAR', 'size' => 32, 'default' => 'bitcoin', 'key' => 'Network'),
'Version' => array('type' => 'INT', 'size' => 10, 'unsigned' => true),
'Mrkl_Root' => array('type' => 'CHAR', 'size' => 64, 'null' => false),
'Time' => array('type' => 'DATETIME'),
'Bits' => array('type' => 'INT', 'size' => 10, 'unsigned' => true),
'Nonce' => array('type' => 'INT', 'size' => 10, 'unsigned' => true),
'Size' => array('type' => 'INT', 'size' => 10, 'unsigned' => true),
'Status' => array('type' => 'ENUM', 'values' => array('pending','confirmed','dropped'), 'default' => 'confirmed', 'null' => false),
),
'Money_Bitcoin_Process_Tx_Out' => [
'Money_Bitcoin_Process_Tx_Out__' => 'UUID',
'Hash' => array('type' => 'CHAR', 'size' => 64, 'null' => false, 'key' => 'UNIQUE:Key'),
'N' => array('type' => 'INT', 'size' => 10, 'unsigned' => true, 'key' => 'UNIQUE:Key'),
'Value' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true, 'null' => false),
'scriptPubKey' => array('type' => 'TEXT'),
'Addr' => array('type' => 'CHAR', 'size' => 40, 'null' => false, 'key' => 'Addr'),
'Trigger' => array('type' => 'ENUM', 'values' => array('new','executed','nil'), 'default' => 'new'),
'_keys' => array(
'Trigger' => array('Trigger'),
),
],
'Money_Bitcoin_Block_Tx' => array(
'Hash' => array('type' => 'CHAR', 'size' => 64, 'null' => false, 'key' => 'UNIQUE:Hash'),
'Block' => array('type' => 'CHAR', 'size' => 64, 'null' => false, 'key' => 'Block'),
'Version' => array('type' => 'INT', 'size' => 10, 'unsigned' => true),
'Lock_Time' => array('type' => 'INT', 'size' => 10, 'unsigned' => true),
'Size' => array('type' => 'INT', 'size' => 10, 'unsigned' => true),
),
/* 'Money_Bitcoin_Block_Tx_In' => array(
'Hash' => array('type' => 'CHAR', 'size' => 64, 'null' => false, 'key' => 'UNIQUE:Key'),
'N' => array('type' => 'INT', 'size' => 10, 'unsigned' => true, 'key' => 'UNIQUE:Key'),
'Prev_Out_Hash' => array('type' => 'CHAR', 'size' => 64, 'null' => false),
'Prev_Out_N' => array('type' => 'INT', 'size' => 10, 'unsigned' => true),
'CoinBase' => array('type' => 'TEXT', 'null' => true),
'scriptSig' => array('type' => 'TEXT', 'null' => true),
'Addr' => array('type' => 'CHAR', 'size' => 40, 'null' => true, 'key' => 'Addr'),
'_keys' => array(
'Prev_Out' => array('Prev_Out_Hash','Prev_Out_N'),
),
),*/
'Money_Bitcoin_Block_Tx_Out' => array(
'Hash' => array('type' => 'CHAR', 'size' => 64, 'null' => false, 'key' => 'UNIQUE:Key'),
'N' => array('type' => 'INT', 'size' => 10, 'unsigned' => true, 'key' => 'UNIQUE:Key'),
'Value' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true, 'null' => false),
'scriptPubKey' => array('type' => 'TEXT'),
'Addr' => array('type' => 'CHAR', 'size' => 40, 'null' => false, 'key' => 'Addr'),
'Claimed' => array('type' => 'ENUM', 'values' => array('Y','N'), 'default' => 'N'),
'Trigger' => array('type' => 'ENUM', 'values' => array('new','executed','nil'), 'default' => 'new'),
'_keys' => array(
'Trigger' => array('Trigger'),
),
),
/* 'Money_Bitcoin_Block_Addr' => array(
'Addr' => array('type' => 'CHAR', 'size' => 40, 'null' => false, 'key' => 'PRIMARY'),
'Network' => array('type' => 'VARCHAR', 'size' => 32, 'default' => 'bitcoin', 'key' => 'Network'),
'Pubkey' => array('type' => 'CHAR', 'size' => 130, 'null' => true),
'Balance' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true, 'null' => false),
'Watch' => array('type' => 'VARCHAR', 'size' => 128, 'null' => true, 'default' => NULL, 'key' => 'Watch'),
'Taint' => array('type' => 'BIGINT', 'size' => 20, 'unsigned' => true, 'null' => true, 'default' => NULL),
'Clean' => array('type' => 'VARCHAR', 'size' => 64, 'null' => true, 'default' => NULL, 'key' => 'Clean'),
), */
'Money_Bitcoin_Vanity' => array(
'Money_Bitcoin_Vanity__' => array('type' => 'VARCHAR', 'size' => 35, 'null' => false, 'key' => 'PRIMARY'),
'Private_Key' => array('type' => 'VARCHAR', 'size' => 255, 'null' => false),
),
);
}
}
\Scheduler::schedule('MoneyBitcoinUpdate', '10min', 'Money/Bitcoin::update');
\Scheduler::schedule('MoneyBitcoinCheckOrders', '5min', 'Money/Bitcoin::checkOrders');
\Scheduler::schedule('MoneyBitcoinGetRate', array('daily', '5i'), 'Money/Bitcoin::getRate');
\Scheduler::schedule('MoneyBitcoinCheckNodes', '10min', 'Money/Bitcoin::checkNodes');
\Scheduler::schedule('MoneyBitcoinImportBlocks', '1min', 'Money/Bitcoin::importBlocks');
\Scheduler::schedule('MoneyBitcoinAddrTriggers', '1min', 'Money/Bitcoin::runAddrTriggers');
\Scheduler::schedule('MoneyBitcoinBroadcastTxs', '1min', 'Money/Bitcoin::broadcastTransactions');
\Scheduler::schedule('MoneyBitcoinMergeSmallOutputs', '10min', 'Money/Bitcoin::mergeSmallOutputs');
\Scheduler::schedule('MoneyBitcoinSplitBigOutputs', '10min', 'Money/Bitcoin::splitBigOutputs');
\DB::i()->validateStruct(Bitcoin::getTablesStruct());