182

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:

10
  • 1
    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. Commented May 12, 2017 at 12:01
  • 1
    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. Commented Jan 16, 2018 at 13:13
  • 12
    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. Commented Jan 27, 2018 at 14:00
  • 19
    @Hey24sheep Your code works? Then post it as answer. I don't believe anybody would downvote you for a working solution. Commented Mar 21, 2018 at 23:29
  • 1
    @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 Commented Mar 22, 2018 at 17:44

1 Answer 1

4

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

Sign up to request clarification or add additional context in comments.

1 Comment

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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.