Это то, что, как мне кажется, должно быть простым, но это сводит меня с ума. См., например, этот список транзакций, связанных с адресом:
https://blockchain.info/address/1EZK42jGEJVniyBn1wXrUx92wzyUkYB8kJ?format=json
Что я хочу сделать, так это просто получить ту же статистику total_received, total_sent и balance для заданных данных.
Очевидное требование – не засчитывать «сдачу» как новый платеж в адрес. Моя идея заключалась в том, чтобы просто суммировать все выходные данные в транзакциях, чьи входные данные не относятся к одному и тому же целевому адресу, например, если транзакция имеет входные данные (или несколько входных данных) из A и выходные данные в B и A, обработайте этот вывод как изменение и не делайте этого. не включать его в сумму — только это не дает той же суммы, что и blockchain.info! В этом случае он выдает 158,11536395 против 251,24164662. Кажется, я что-то упускаю?
Следующим шагом будет получение списка результатов, полученных на первом этапе, и просмотр, какие из них потрачены, а какие нет. Сумма неизрасходованных выходов и есть текущий баланс. Это правильно?
Кто угодно?
Как отмечалось в другом ответе, для определенного адреса технически не существует баланса. Это связано с тем, что может быть много выходов, которые адресованы на адрес, которым вы владеете, но вы можете тратить эти выходы только дискретно (т.е. вы можете сказать вычесть x с моей учетной записи, вы можете только сказать вычесть эту сумму вывода, которая ранее была присуждена этому адрес).
Однако мы можем определить псевдопонятие баланса, назовем его разблокируемым значением адреса (UV), потому что владелец закрытого ключа для этого адреса может разблокировать некоторое количество монет, зная закрытый ключ для этого адреса. адрес.
Теперь, чтобы рассчитать баланс UV, общее количество полученных и отправленных адресов, вы следуете этому псевдоалгоритму:
Address a;
Uv = 0;
Received = 0;
Sent = 0;
For each (output in blockchain):
If (output is unlock-able by owner of address a):
Received += output.amount;
If (output has been spent):
Sent += output.amount;
Else:
Uv += output.amount;
В конце всех выходов в блокчейне сумма Uv будет иметь значение, аналогичное концепции баланса. Но здесь мы также можем увидеть, почему это очень сложное понятие:
Я подозреваю, что способ, которым blockchain.info делает это, в основном запускается вышеописанным псевдоалгоритмом (хотя он гораздо более оптимизирован и использует базу данных), но только с учетом выходных данных в формате Pay-to-Pubkey-Hash.
Хорошо, связавшись со службой поддержки blockchain.info и проведя некоторые тесты, я обнаружил, что проблема заключалась в том, что ссылка на API, указанная в вопросе, разбита на страницы и ограничена по скорости. Следующий PHP-код выдает те же значения, которые blockchain.info показывает на своем сайте, при условии, что вы не столкнетесь с проблемами ограничения скорости.
<?php
// Method: POST, PUT, GET etc
// Data: array("param" => "value") ==> index.php?param=value
function CallAPI($method, $url, $data = false)
{
$curl = curl_init();
switch ($method)
{
case "POST":
curl_setopt($curl, CURLOPT_POST, 1);
if ($data)
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
break;
case "PUT":
curl_setopt($curl, CURLOPT_PUT, 1);
break;
default:
if ($data)
$url = sprintf("%s?%s", $url, http_build_query($data));
}
// Optional Authentication:
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
// curl_setopt($curl, CURLOPT_USERPWD, "username:password");
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($curl);
curl_close($curl);
return $result;
}
$address = "1EZK42jGEJVniyBn1wXrUx92wzyUkYB8kJ";
$offset=0;
$txs = array();
while (true)
{
$val = json_decode(CallAPI("GET", "https://blockchain.info/address/$address?format=json&limit=10&offset=$offset"), true);
if (count($val["txs"]) == 0)
break;
else
$txs = array_merge($txs, $val["txs"]);
$offset += 10;
}
$uv = 0;
$received = 0;
$sent = 0;
$nrefs = 0;
foreach ($txs as $tx)
{
$ininputs = false;
$totalin = 0;
foreach ($tx["inputs"] as $input)
{
if ($input["prev_out"]["addr"] == $address)
{
$ininputs = true;
$nrefs += 1;
$totalin += $input["prev_out"]["value"];
}
}
$inoutputs = false;
$totalout = 0;
foreach ($tx["out"] as $output)
{
if ($output["addr"] == $address)
{
$inoutputs = true;
$nrefs += 1;
$totalout += $output["value"];
}
}
$uv += ($totalout - $totalin);
// $received += $totalout;
// $sent += $totalin;
if ($ininputs && $inoutputs && $totalout >= $totalin)
{
$received += $totalout - $totalin;
}
else if ($ininputs && $inoutputs && $totalout < $totalin)
{
$sent += $totalin - $totalout;
}
else if ($inoutputs)
{
$received += $totalout;
}
else if ($ininputs)
{
$sent += $totalin;
}
}
echo "\n";
echo "nrefs : " . $nrefs . "\n";
echo "uv : " . $uv . "\n";
echo "received : " . $received . "\n";
echo "sent : " . $sent . "\n";
Сумма неизрасходованных выходов и есть текущий баланс.
Не совсем, это просто неизрасходованные выходы для определенного хэша pubkeyhash. Балансов в биткойнах не существует, и людей будет крайне обманывать, предполагая, что они существуют, используя эту терминологию.
Что я хочу сделать, так это просто получить ту же статистику total_received, total_sent и balance для заданных данных.
Это не часть сети, поэтому даже не определено, что этот термин может означать. Отображаемая информация не согласуется между веб-сайтами, утверждающими, что они могут отображать «всего полученное» для адреса.
Инсайт говорит 521.29736505 BTC
blockchain.info говорит 251,24164662 BTC
chain.so говорит 389,85919867 BTC
blockcypher.com говорит 289,5535 BTC
webbtc.com говорит 521.29736505 BTC
Chain.com говорит 251,24164662 BTC
blockchains.io говорит 1042,59473010 BTC
helloblock.io говорит 217.80681263 BTC
Так кто прав?
Лучше просто не путать всех, показывая неверные данные для начала. Экстраполяция этой информации на людей не приносит никакой пользы, и если сервисы строятся с использованием такого рода ошибочных предположений о поведении сети, это может быть потенциально катастрофическим и привести к потере средств.
Balances don't exist in Bitcoin,
Это может быть правдой на уровне протокола, но люди не создают биткойн-транзакции напрямую — они используют клиентов, которые абстрагируются от этих деталей. Я имею в виду, вы можете применить аналогичную логику, чтобы сказать, что доменных имен не существует, поскольку вы действительно общаетесь с IP-адресом.A "balance" implies many things that are just simply not applicable.
И то, что вы открываете свой веб-браузер для доменного имени, также подразумевает вещи, которые не соответствуют действительности. И тем не менее, это полезная абстракция. I don't think anybody actually understands how anybody else is calculating this,
Верно для total_received, но баланс определен гораздо лучше.Некоторые из этих ответов абсурдны. Да, есть разница между наличием ключа для траты с адреса и простым суммированием. Но если у вас есть пара ключей, которую вы можете потратить с адреса, ее окончательная сумма в точности соответствует «расходуемому балансу».
Я понятия не имею, как исследователи блоков не могут прийти к единому мнению относительно остатков на счетах. Я предполагаю, что большие числа являются точными суммами адресов ввода/вывода. Неточные будут ниже и будут неточными, вероятно, потому, что они не вычисляют должным образом базу монет для каждого ввода, который заканчивается адресом и не тратится.
Значения Coinbase не хранятся в цепочке, они находятся в параметрах цепочки, что можно назвать «эфемерным консенсусом». Значения Coinbase рассчитываются в соответствии с графиком халвинга вознаграждения за блок. Получение другой суммы в конце может быть только потому, что вы не считаете все действительные входы и выходы, из которых coinbase очень важна.
Coinbase values are not stored in the chain, they are in the chain parameters
. Это неверно, текущее вознаграждение за блок + сборы очень сильно зависят от цепочки, в результате транзакции coinbase. Любой обозреватель блоков, суммирующий выходные данные, должен иметь возможность подобрать его без дополнительной работы.
морсекодер
морсекодер