Query LOCAL Bitcoin blockchain with C# .NET

11,118

The first and second attempts in your question are nothing alike. First one uses json rpc to ask the daemon for the balance (and I dare say it's the proper way - you don't take the top off your car engine and push the pistons up and down yourself to achieve forward motion, do you?) the second attempts to open the daemon's database itself and calculate the balance directly.

You don't "need a network" to query the localhost, you just need a machine that has TCP/IP support installed, so just use the first method by whatever means - either by using a library that writes the relevant json-rpc data into an http request, or by forming the relevant http request yourself..

BitcoinLib may or may not be maintained (I don't know) but that doesn't invalidate its ability to query your local daemon; as far as I know GetBalance hasn't been removed or refactored, and I use BitcoinLib with the latest bitcoind for a variety of operations including GetBalance

Share:
11,118

Related videos on Youtube

rvnlord
Author by

rvnlord

I am a C# .NET developer passionate about blockchain, cryptocurrencies, clever data gathering automation and predictive market analysis among other things. I also have knowledge, supported by examples on github, on how to implement the above. I've been coding mainly WPF, ASP.NET MVC, JavaScript (with JQuery), REST API, Selenium, Xamarin, some WCF, MSSQL, MySQL and Oracle. I also have some limited knowledge about Java, NodeJS and Lua. Currently I have no official jobs on the record except for 2 internships. CV: https://github.com/rvnlord/CV

Updated on July 28, 2020

Comments

  • rvnlord
    rvnlord almost 4 years

    I am trying to check the balance of a given Bitcoin address by using ONLY the locally stored blockchain (downloaded via Bitcoin Core). Something similar to this (by using NBitCoin and/or QBitNinja), but without needing access to the network:

    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;
    }
    

    The example above needs access to the network. I need to do the same thing offline. I came up with something like this, but obviously it doesn't work:

    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. It hangs during the query
    2. I want something instead of InMemoryNoSqlRepository to be stored in a file in order to prevent using ReIndex() which slows everything down

    My requirement is to Check Balance the same way as in the first method but by querying blocks stored on my disk.

    Actually what I require might just be an answer to this question:

    • Evk
      Evk about 7 years
      Is using QBitNinja a requirement? Because I remember I did the same with BitcoinLib some years ago (memories are quite rusty but I'm sure I had local bitcoin node and used that to query different kind of stuff, including balance).
    • rvnlord
      rvnlord about 7 years
      Ideally I would like to use NBitcoin only like in my second method which doesn't work and I don't know why. QBitNinja Server on IIS is my second option, but as you mentioned BitcoinLib, I might give it a try as a last resort. Balance here is just an example, I would like to query local blockchain for many interesting things. Though I thought that BitcoinLib is not updated anymore. I appreciate any help and it looks like you are the only one who is trying so far :). So yes I will give you the 50 rep if no one give better answer.
    • Evk
      Evk about 7 years
      Well last commit was 7 months ago, not that long ago (and there is pending pull request by contibutor in march current year), so I wouldn't say it's not updated any more. As for querying for many interesting things - BitcoinLib is just a proxy to official RPC api, so I guess you can query everything with it. Though of course if you already put some work into QBitNinja I understand you might want to stick with it.
    • RLH
      RLH over 6 years
      I don't have a local node but I worked with blockchain code a good bit about 4 years ago. I can give a very good educated guess that the reason why this may be taking so long is the way the serialized blockchain data is structured and the way the linq engine queries that data. I suspect that your routine is "hanging" because the underlying parsing/querying code isn't optimized. Your code is very-likely working but it may need some underlying optimizations for responsive execution.
    • Hey24sheep
      Hey24sheep over 6 years
      Hi, it's an old question but I saw this yesterday. I tried your code with NBitcoin. Your code works on my partial old local node only if I comment this line index.ReIndex(); and this line var chain = node.GetChain();. I also tweaked my code a little bit that instead of GetChain I did GetBlocks. and simillar changes to make it work. I don't want to get downvoted so I am posting this comment :) . I hope it helps you.
    • Martin Braun
      Martin Braun over 6 years
      @Hey24sheep Your code works? Then post it as answer. I don't believe anybody would downvote you for a working solution.
    • Hey24sheep
      Hey24sheep over 6 years
      @modiX and Kobik, I couldn't find my project and I don't have the node now So I can't reproduce it, idk Why (Might be that my node needs to be synced before I can do anything). I found out that this is obsolete method anyway. We should use some explorer or something now. github.com/MetacoSA/NBitcoin/issues/332
    • Hey24sheep
      Hey24sheep over 6 years
    • Rich Bianco
      Rich Bianco about 6 years
      Why are people afraid to post a solution and get down voted? Is this a sign that Bitcoin is not what we think it is? Should I NOT be concerned as a Bitcoin speculator? Referring to comment made by @Hey24sheep and others. Yellow flag time?
    • rvnlord
      rvnlord almost 6 years
      @Hey24sheep: Kindly post it as an answer with code snippet so I can mark it as accepted answer, thanks.
    • Hey24sheep
      Hey24sheep almost 6 years
      @rvnlord Hi, I am sorry but I don't have the code and the node to check it back. I tried it again when I was responded to but I wasn't able to get the same results that I got before. I did that long ago.
    • Kevin Cruijssen
      Kevin Cruijssen almost 6 years
      @Hey24sheep Just a tip for next time: even if you post an answer and get downvoted, deleting it will get you all your points back anyway.. Besides, as others have mentioned, if you have a working solution with proper explanation in your answer, I don't see any reason why someone would downvote you for it.
    • Hey24sheep
      Hey24sheep over 5 years
      @KevinCruijssen I will remember it the next time. I had a working solution. I am just afraid of downvotes, cuz I have been downvoted for right answers in the past.
    • rvnlord
      rvnlord over 5 years
      @Hey24sheep You can be downvoted for correct answer, working solution, valid question, speaking the truth or for nothing at all. Don't let such silly things define you. If your knowledge adds value to the topic and helps somebody, that is the most important thing. Don't let anyone discourage you. I corrected the code, thanks to your advice sometime earlier, however I can't test it against the local node because I don't have one anymore. I am grateful for your contribution though. If you provide working solution as an answer, whenever you feel ready, I will make sure you receive a bounty.
    • Hey24sheep
      Hey24sheep over 5 years
      @rvnlord I don't have the solution or the node. I will keep it in mind for the next time though :) Thanks
  • rvnlord
    rvnlord almost 6 years
    I completely forgot about this question. @Hey24sheep solved the problem, though I don't have full local node available now. I needed attempt to query LOCAL and OFFLINE data back then. I needed to query it much faster than I can achieve by using APIs to 3rd party sources.