我需要选择最佳比特币交易组合进行发送。我使用PHP实现了结果,但它使用了大量内存,数据库很有可能处理得更好。
整个交易清单:
+------------------+------+--------+
| Transaction ID | Vout | Amount |
+------------------+------+--------+
| transactionid1 | 0 | 10 |
| transactionid1 | 1 | 1.5 |
| transactionid2 | 0 | 0.5 |
| transactionid3 | 0 | 0.7 |
+------------------+------+--------+
我需要创建某种函数或选择查询,当我提供金额= 0.4时,它会返回我的行
+------------------+------+--------+
| Transaction ID | Vout | Amount |
+------------------+------+--------+
| transactionid2 | 0 | 0.5 |
+------------------+------+--------+
当我提供金额= 2.1
时+------------------+------+--------+
| Transaction ID | Vout | Amount |
+------------------+------+--------+
| transactionid1 | 1 | 1.5 |
| transactionid3 | 0 | 0.7 |
+------------------+------+--------+
所以剩下的就是Knapsack problem了。这是我如何使用组合学解决我的问题。我已将交易数据压缩为$ key => $ value数组,其中$ key是transactionid_vout,value是amount。
$flatterTransactions = array(4) ( [transactionid1_0] => (int) 10 [transactionid1_1] => (float) 1.5 [transactionid2_0] => (float) 0.5 [transactionid3_0] => (float) 0.7 )
然后我从该交易中创建组合
$combinations = array(15) ( [0] => Array ( [transactionid1_0] => 10 ) [1] => Array ( [transactionid1_1] => 1.5 ) [2] => Array ( [transactionid2_0] => 0.5 ) [3] => Array ( [transactionid3_0] => 0.7 ) [4] => Array ( [transactionid1_0] => 10 [transactionid1_1] => 1.5 ) [5] => Array ( [transactionid1_0] => 10 [transactionid2_0] => 0.5 ) [6] => Array ( [transactionid1_0] => 10 [transactionid3_0] => 0.7 ) [7] => Array ( [transactionid1_1] => 1.5 [transactionid2_0] => 0.5 ) [8] => Array ( [transactionid1_1] => 1.5 [transactionid3_0] => 0.7 ) [9] => Array ( [transactionid2_0] => 0.5 [transactionid3_0] => 0.7 ) [10] => Array ( [transactionid1_0] => 10 [transactionid1_1] => 1.5 [transactionid2_0] => 0.5 ) [11] => Array ( [transactionid1_0] => 10 [transactionid1_1] => 1.5 [transactionid3_0] => 0.7 ) [12] => Array ( [transactionid1_0] => 10 [transactionid2_0] => 0.5 [transactionid3_0] => 0.7 ) [13] => Array ( [transactionid1_1] => 1.5 [transactionid2_0] => 0.5 [transactionid3_0] => 0.7 ) [14] => Array ( [transactionid1_0] => 10 [transactionid1_1] => 1.5 [transactionid2_0] => 0.5 [transactionid3_0] => 0.7 ) )
然后我通过组合并用得分创建总和组合数组。这里的评分目标是使用更少的交易。
$summedCombinations[$key] = array(
'sum' => $sum,
'count' => count($combination),
'score' => $sum * (count($combination) * 2)
);
毕竟我按照字段过滤数组,只留下覆盖我金额的交易。按分数排序并获得最佳匹配。
答案 0 :(得分:0)
最好在这里有点问题,但这就是我如何去做。无论你如何做,你都必须处理一个选择组合的算法。
WITH target AS (select ? as target),
RECURSIVE largest_txs AS (
select transaction_id, vout, amount, amount as running_total
from transactions
CROSS JOIN target
where amount < target.target
order by amount desc limit 1
UNION ALL
SELECT t.transaction_id, t.vout, t.amount, t.amount + l.running_total
FROM transactions
JOIN (select * from largest_txs order by amount asc limit 1) l
CROSS JOIN target
WHERE amount < target.target + l.running_total AND t.transaction_id NOT IN
(select transaction_id from largest_txs)
)
SELECT transaction_id, vout, amount, running_total FROM largest_txs
UNION
SELECT t.transaction_id, t.vout, t.amount, null
FROM transactions t
WHERE t.transaction_id NOT IN (select transaction_id from largest_txs)
ORDER BY amount asc limit 1;
这应该是可以预期的。如果表格具有任何大小,你肯定会想要一个金额索引。