Zapytaj LOCAL Bitcoin blockchain za pomocą C # .NET

175

Próbuję sprawdzić saldo podanego adresu Bitcoin, używając TYLKO lokalnie przechowywanego blockchaina (pobieranego przez Bitcoin Core). Coś podobnego do tego (przy użyciu NBitCoin i / lub QBitNinja), ale bez konieczności dostępu do sieci:

private static readonly QBitNinjaClient client = new QBitNinjaClient(Network.Main);

public decimal CheckBalance(BitcoinPubKeyAddress address)
{
    var balanceModel = client.GetBalance(address, true).Result;
    decimal balance = 0;

    if (balanceModel.Operations.Count > 0)
    {
        var unspentCoins = new List<Coin>();
        foreach (var operation in balanceModel.Operations)
            unspentCoins.AddRange(operation.ReceivedCoins.Select(coin => coin as Coin));
        balance = unspentCoins.Sum(x => x.Amount.ToDecimal(MoneyUnit.BTC));
    }
    return balance;
}

Powyższy przykład wymaga dostępu do sieci. Muszę zrobić to samo w trybie offline. Wymyśliłem coś takiego, ale oczywiście to nie działa:

public decimal CheckBalanceLocal(BitcoinPubKeyAddress address)
{
    var node = Node.ConnectToLocal(Network.Main);
    node.VersionHandshake();
    var chain = node.GetChain();

    var store = new BlockStore(@"F:\Program Files\Bitcoin\Cache\blocks", Network.Main);

    var index = new IndexedBlockStore(new InMemoryNoSqlRepository(), store);
    index.ReIndex();

    var headers = chain.ToEnumerable(false).ToArray();

    var balance = (
        from header in headers
        select index.Get(header.HashBlock) 
        into block
        from tx in block.Transactions
        from txout in tx.Outputs
        where txout.ScriptPubKey.GetDestinationAddress(Network.Main) == address
        select txout.Value.ToDecimal(MoneyUnit.BTC)).Sum();

    return balance;
}
  1. Zawiesza się podczas zapytania
  2. Chcę, aby coś zamiast InMemoryNoSqlRepositorybyło przechowywane w pliku, aby zapobiec używaniu, ReIndex()które spowalnia wszystko

Moim wymaganiem jest sprawdzenie salda w taki sam sposób, jak w pierwszej metodzie, ale poprzez odpytywanie bloków przechowywanych na moim dysku.

Właściwie to, czego potrzebuję, może być odpowiedzią na to pytanie :

rvnlord
źródło
1
Idealnie chciałbym używać NBitcoin tylko tak, jak w mojej drugiej metodzie, która nie działa i nie wiem dlaczego. QBitNinja Server on IIS to moja druga opcja, ale jak wspomniałeś o BitcoinLib, mogę spróbować w ostateczności. Saldo to tylko przykład, chciałbym zapytać lokalny łańcuch bloków o wiele interesujących rzeczy. Chociaż myślałem, że BitcoinLib nie jest już aktualizowany. Doceniam każdą pomoc i wygląda na to, że jesteś jedyną osobą, która do tej pory próbuje :). Więc tak, dam ci 50 powtórzeń, jeśli nikt nie poda lepszej odpowiedzi.
rvnlord
1
Nie mam lokalnego węzła, ale pracowałem z kodem blockchain około 4 lata temu. Mogę się domyślić, że powodem, dla którego może to trwać tak długo, jest struktura zserializowanych danych łańcucha bloków oraz sposób, w jaki silnik linq wyszukuje te dane. Podejrzewam, że twoja procedura "zawiesza się", ponieważ bazowy kod parsowania / zapytań nie jest zoptymalizowany. Twój kod prawdopodobnie działa, ale może wymagać pewnych podstawowych optymalizacji w celu szybkiego wykonania.
RLH
12
Cześć, to stare pytanie, ale widziałem je wczoraj. Wypróbowałem twój kod z NBitcoin. Twój kod działa na moim częściowym starym węźle lokalnym tylko wtedy, gdy skomentuję ten wiersz index.ReIndex (); a ta linia var chain = node.GetChain () ;. Poprawiłem też trochę kod, że zamiast GetChain zrobiłem GetBlocks. i podobne zmiany, aby to działało. Nie chcę być negatywnie ocenianym, więc zamieszczam ten komentarz :). Mam nadzieję, że Ci to pomoże.
Hey24sheep
19
@ Hey24sheep Twój kod działa? Następnie opublikuj to jako odpowiedź. Nie sądzę, by ktokolwiek zlekceważył cię za działające rozwiązanie.
Martin Braun
5
Dlaczego ludzie boją się opublikować rozwiązanie i stracić głos w głosowaniu? Czy to znak, że Bitcoin nie jest tym, czym myślimy, że jest? Czy NIE powinienem się martwić jako spekulant Bitcoin? Nawiązując do komentarza @ Hey24sheep i innych. Czas z żółtą flagą?
Rich Bianco

Odpowiedzi:

1

Pierwsza i druga próba twojego pytania nie są do siebie podobne. Pierwszy z nich używa json rpc, aby zapytać demona o równowagę (i śmiem twierdzić, że to właściwy sposób - nie zdejmujesz górnej części silnika samochodu i nie naciskasz tłoków w górę iw dół, aby uzyskać ruch do przodu, prawda?) drugi próbuje otworzyć samą bazę danych demona i bezpośrednio obliczyć saldo.

Nie potrzebujesz sieci do wysyłania zapytań do lokalnego hosta, potrzebujesz tylko maszyny z zainstalowaną obsługą TCP / IP, więc po prostu użyj pierwszej metody w jakikolwiek sposób - albo używając biblioteki, która zapisuje odpowiednie dane json-rpc do żądania http lub samodzielnie tworząc odpowiednie żądanie http.

BitcoinLib może być utrzymywany lub nie (nie wiem), ale to nie unieważnia jego możliwości wysyłania zapytań do lokalnego demona; o ile wiem, GetBalance nie został usunięty ani refaktoryzowany, a używam BitcoinLib z najnowszym bitcoindem do różnych operacji, w tym GetBalance

Caius Jard
źródło
Zupełnie zapomniałem o tym pytaniu. @ Hey24sheep rozwiązał problem, chociaż nie mam teraz pełnego węzła lokalnego. Potrzebowałem wtedy próby przeszukania danych LOKALNYCH i OFFLINE. Musiałem zapytać o to znacznie szybciej, niż mogę to osiągnąć, używając interfejsów API do źródeł zewnętrznych.
rvnlord