function cancel_order($orderid, $uid) { // cancel an order $query = "\n UPDATE orderbook\n SET status='CANCEL'\n WHERE\n orderid='{$orderid}'\n AND uid='{$uid}'\n AND status='OPEN'\n "; do_query($query); if (mysql_affected_rows() != 1) { if (mysql_affected_rows() > 1) { throw new Error('Serious...', 'More rows updated than should be. Contact the sysadmin ASAP.'); } else { if (mysql_affected_rows() == 0) { throw new Problem(_('Cannot...'), _('Your order got bought up before you were able to cancel.')); } else { throw new Error('Serious...', 'Internal error. Contact sysadmin ASAP.'); } } } // Refetch order in case something has happened. $info = fetch_order_info($orderid); if ($uid != $info->uid) { throw new Error('Permission...', '... Denied! Now GTFO.'); } add_funds($info->uid, $info->amount, $info->type); // these records indicate returned funds. create_record($orderid, $info->amount, 0, 0, -1, 0); addlog(LOG_RESULT, " cancelled order {$orderid}"); }
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); }
require_once 'view_util.php'; if (isset($_POST['cancel_order'])) { if (isset($_POST['csrf_token'])) { if ($_SESSION['csrf_token'] != $_POST['csrf_token']) { throw new Error("csrf", "csrf token mismatch!"); } } else { throw new Error("csrf", "csrf token missing!"); } } if (!isset($_GET['orderid'])) { throw new Problem(_('No order selected'), _('Hit back and select an order.')); } $orderid = get('orderid'); $uid = user_id(); $info = fetch_order_info($orderid); if ($is_admin) { $uid = $info->uid; } else { if ($info->uid != $uid) { throw new Problem('Not for your eyes', "This isn't your order."); } } if (isset($_POST['cancel_order'])) { cancel_order($orderid, $uid); ?> <div class='content_box'> <h3>Cancelled!</h3> <p>Order <?php echo $orderid; ?>