function fulfill_order($our_orderid) { $our = fetch_order_info($our_orderid); if ($our->status != 'OPEN') { return; } if ($our->processed) { throw new Error('Unprocessed', "Shouldn't be here for {$our_orderid}"); } // Dividing two bignum(20) values only gives us 4 decimal places in the result // this can cause us to process the matching orders out of sequence unless we arrange // for the quotient to be greater than 1 by putting the bigger value on top. // // With BTC at around 10 GBP each, I just saw the previous version of this query // process 2 orders out of sequence because the values of initial_want_amount / initial_amount // for the two orders were 0.09348 and 0.09346, which compare equal to 4 decimal places if ($our->initial_amount > $our->initial_want_amount) { $order_by = "initial_want_amount / initial_amount ASC"; } else { $order_by = "initial_amount / initial_want_amount DESC"; } $query = "\n SELECT orderid, uid\n FROM orderbook\n WHERE\n status='OPEN'\n AND processed=TRUE\n AND type='{$our->want_type}'\n AND want_type='{$our->type}'\n AND initial_amount * '{$our->initial_amount}' >= initial_want_amount * '{$our->initial_want_amount}'\n AND uid!='{$our->uid}'\n ORDER BY {$order_by}, timest ASC;\n "; wait_for_lock($our->uid); $result = b_query($query); while ($row = mysql_fetch_array($result)) { echo "Found matching ", $row['orderid'], " from user ", $row['uid'], ".\n"; wait_for_lock($row['uid']); // lock their account $them = fetch_order_info($row['orderid']); // re-fetch their order now that they're locked if ($them->status != 'OPEN') { echo "order {$them->orderid} was cancelled on us\n"; release_lock($them->uid); continue; } printf("old order: has %s; wants %s\n", internal_to_numstr($them->amount), internal_to_numstr($them->want_amount)); if ($them->type != $our->want_type || $our->type != $them->want_type) { throw Error('Problem', 'Urgent problem. Contact the site owner IMMEDIATELY.'); } // echo " them: orderid {$them->orderid}, uid {$them->uid}, have {$them->amount} {$them->type}, want {$them->want_amount}\n"; // echo " us: orderid {$our->orderid}, uid {$our->uid }, have: {$our->amount} {$our->type}, want {$our->want_amount}\n"; // echo " them->initial_amount = {$them->initial_amount}, them->initial_want_amount = {$them->initial_want_amount}\n"; $left = gmp_mul($our->amount, $them->initial_amount); $right = gmp_mul($them->amount, $them->initial_want_amount); if (gmp_cmp($left, $right) >= 0) { // We need to calculate how much of our stuff they can afford at their price // we ignore the remainder - it's totally insignificant. list($them->new_want, $remainder) = gmp_div_qr($right, $them->initial_amount); if (gmp_cmp($remainder, 0) != 0) { $them->new_want = gmp_add($them->new_want, 1); } $them->new_want = gmp_strval($them->new_want); echo " we swallow them; they can afford {$them->new_want} from us\n"; pacman($them->orderid, $them->uid, $them->amount, $them->type, $them->commission, $our->orderid, $our->uid, $them->new_want, $our->type, $our->commission, $our->amount, $our->initial_amount, $our->initial_want_amount); release_lock($them->uid); // re-update as still haven't finished... // info needed for any further transactions $our = fetch_order_info($our->orderid); // order was closed and our job is done. if ($our->status != 'OPEN') { break; } } else { // We need to calculate how much of their stuff we can afford at their price // we ignore the remainder - it's totally insignificant. list($our->new_want, $remainder) = gmp_div_qr($left, $them->initial_want_amount); if (gmp_cmp($remainder, 0) != 0) { $our->new_want = gmp_add($our->new_want, 1); } $our->new_want = gmp_strval($our->new_want); echo " they swallow us; we can afford {$our->new_want} from them\n"; pacman($our->orderid, $our->uid, $our->amount, $our->type, $our->commission, $them->orderid, $them->uid, $our->new_want, $our->want_type, $them->commission, $them->amount, $them->initial_amount, $them->initial_want_amount); release_lock($them->uid); break; } } release_lock($our->uid); }
<ul> <li><a href="http://code.google.com/p/googlechartphplib/">Project home on Google Code</a></li> <li><a href="http://code.google.com/p/googlechartphplib/issues/list">Issue Tracker</a></li> <li><code>remi at cloudconnected dot fr</code></li> </ul> </div> <div class="clear"></div> </div> <div id="footer"> <h3>About</h3> <p>I'm Rémi Lanvin, and you can contact me by email at <code>remi at cloudconnected dot fr</code></p> <p>Sometimes I have enough free time to write an article <a href="http://cloudconnected.fr">on my dev blog</a>, or something <a href="http://twitter.com/rlanvin">on my Twitter account</a>.</p> <p id="pacman"><img src="<?php echo pacman(); ?> " alt="Tribute to Pacman with a Pie Chart" title="Tribute to Pacman with a Pie Chart"></p> </div> </div> <script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-11912505-4']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();