Bitcoin Forum
May 21, 2024, 05:04:24 PM *
News: Latest Bitcoin Core release: 27.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Get UTXOs of a wallet...  (Read 127 times)
sudonims (OP)
Newbie
*
Offline Offline

Activity: 2
Merit: 2


View Profile
March 28, 2022, 01:47:34 PM
Merited by ABCbits (1), PrimeNumber7 (1)
 #1

I'm trying to work on something and I need a programmatic way to get UTXOs related to a certain wallet...


e.g, if I run a btc-core node with wallet A having addresses [A1,...,A10], then I want a programmatic way to get a set of all UTXOs related to wallet A i.e for addresses [A1,...,A10]... Preferrebly in C++... Thanks in advance...
BlackHatCoiner
Legendary
*
Online Online

Activity: 1526
Merit: 7398


Farewell, Leo


View Profile
March 28, 2022, 01:53:35 PM
Merited by pooya87 (2)
 #2

In Bitcoin Core you can use:
Code:
bitcoin-cli listunspent
(dev link)

in3rsha has also written this: bitcoin-utxo-dump. (In Go language)

.
.BLACKJACK ♠ FUN.
█████████
██████████████
████████████
█████████████████
████████████████▄▄
░█████████████▀░▀▀
██████████████████
░██████████████
████████████████
░██████████████
████████████
███████████████░██
██████████
CRYPTO CASINO &
SPORTS BETTING
▄▄███████▄▄
▄███████████████▄
███████████████████
█████████████████████
███████████████████████
█████████████████████████
█████████████████████████
█████████████████████████
███████████████████████
█████████████████████
███████████████████
▀███████████████▀
█████████
.
n0nce
Hero Member
*****
Offline Offline

Activity: 882
Merit: 5829


not your keys, not your coins!


View Profile WWW
March 28, 2022, 01:56:19 PM
 #3

I'm trying to work on something and I need a programmatic way to get UTXOs related to a certain wallet...


e.g, if I run a btc-core node with wallet A having addresses [A1,...,A10], then I want a programmatic way to get a set of all UTXOs related to wallet A i.e for addresses [A1,...,A10]... Preferrebly in C++... Thanks in advance...
I can't provide you code right now, but these are the RPC commands that you should look into:

Wallet RPCs

I also found this resource that shows how to call RPC methods from Python using simple network requests. Should be easy to follow along and code it in C++.

Code: (https://upcoder.com/7/bitcoin-rpc-from-python/)
~snip~
headers = {'content-type': 'application/json'}
payload = json.dumps({"method": 'getblock', "params": ["0000000000005e5fd51f764d230441092f1b69d1a1eeab334c5bb32412e8dc51"], "jsonrpc": "2.0"})
response = requests.get(serverURL, headers=headers, data=payload)
~snip~

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
sudonims (OP)
Newbie
*
Offline Offline

Activity: 2
Merit: 2


View Profile
March 28, 2022, 01:57:42 PM
 #4

In Bitcoin Core you can use:
Code:
bitcoin-cli listunspent
(dev link)

in3rsha has also written this: bitcoin-utxo-dump. (In Go language)

Thanks... I will check it out...
n0nce
Hero Member
*****
Offline Offline

Activity: 882
Merit: 5829


not your keys, not your coins!


View Profile WWW
March 28, 2022, 02:46:13 PM
Last edit: March 30, 2022, 02:58:38 PM by n0nce
Merited by BlackHatCoiner (2), ABCbits (1), PrimeNumber7 (1)
 #5

Okay, I had a few minutes and threw something together using this one-file HTTP lib for C++ and the example in Python I linked to, earlier.
It's not fully working yet, but it should be a good starting point. Smiley

It might actually run, honestly, just don't have RPC credentials handy right now.
This leverages the built-in local HTTP API that Bitcoin Core offers. If you want to go through the RPC interface, that should also work, but I believe this is much easier by avoiding permission issues to the RPC interface for instance.

Code:
#define CPPHTTPLIB_OPENSSL_SUPPORT
#include "./httplib.h"

int main() {
  int rpcPort = 8332;
  std::string rpcUser = "bitcoinrpc";
  std::string rpcPassword = "";
  std::string serverURL = "http://" + rpcUser + ":" + rpcPassword + "@localhost:" + std::to_string(rpcPort);

  httplib::Headers headers = {{"content-type", " application/json"}};
  std::string body = "{'method': 'getblock', 'params': ['0000000000005e5fd51f764d230441092f1b69d1a1eeab334c5bb32412e8dc51'], 'jsonrpc': '2.0'}";

  httplib::Client client(serverURL);

  if (auto res = client.Post("", headers, body, "application/json")) {
    std::cout << res->status << std::endl;
    std::cout << res->body << std::endl;
  } else {
    auto err = res.error();
    std::cout << "[Error]: " <<  err << std::endl;
  }
}

Compile & link right libraries: g++ -lssl -lcrypto bitcointest.cpp -o bitcointest


Edit: There's some issues with this, especially if your node is configured to use a cookie file like mine.

I checked the bitcoin-cli source code and we can see that the cookie content is passed in the HTTP request header.
This function call retrieves the cookie's contents and stores them in strRPCUserColonPass.

This line adds its BASE64-encoding to the Authentication header.
Code:
evhttp_add_header(output_headers, "Authorization", (std::string("Basic ") + EncodeBase64(strRPCUserColonPass)).c_str());

When comparing to the Python project I linked earlier, make sure not to use a GET request, but POST instead, as evidenced by this line (EVHTTP_REQ_POST).

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
n0nce
Hero Member
*****
Offline Offline

Activity: 882
Merit: 5829


not your keys, not your coins!


View Profile WWW
March 30, 2022, 05:29:33 PM
Last edit: March 30, 2022, 06:01:07 PM by n0nce
Merited by ABCbits (2)
 #6

Alright guys, I got it working with the .cookie file.
As we can see from Bitcoin Core code, the cookie file specifies a HTTP Basic Auth user named __cookie__ and a random password that changes after each restart of Bitcoin Core.
It is also explained quite well here on StackOverflow: __cookie__ is the basic auth username and abc123 is a randomly generated password.

Therefore, it's enough to add those values to a normal HTTP request.
A MVP example using cURL would be (replacing xxxxx with actual content from the .cookie file):
Code:
curl --user __cookie__:xxxxx -X POST -H 'Content-Type: application/json' -H 'X-Auth-Token: undefined' --data-raw '{"id":1, "jsonrpc":"2.0", "method":"getblockchaininfo"}' http://127.0.0.1:8332

It correctly returns:
Code:
{
  "result": {
    "chain": "main",
    "blocks": 729713,
    "headers": 729713,
    "bestblockhash": "000000000000000000000fbfac1a91cdeaf64d689f7673d02613da9d10bfb284",
    "difficulty": 27452707696466.39,
    "mediantime": 1648651391,
    "verificationprogress": 0.9999999227202188,
    "initialblockdownload": false,
    "chainwork": "00000000000000000000000000000000000000002b2a9f5f3ef98696e155655c",
    "size_on_disk": 452426899872,
    "pruned": false,
    "softforks": {
      "bip34": {
        "type": "buried",
        "active": true,
        "height": 227931
      },
      "bip66": {
        "type": "buried",
        "active": true,
        "height": 363725
      },
      "bip65": {
        "type": "buried",
        "active": true,
        "height": 388381
      },
      "csv": {
        "type": "buried",
        "active": true,
        "height": 419328
      },
      "segwit": {
        "type": "buried",
        "active": true,
        "height": 481824
      },
      "taproot": {
        "type": "bip9",
        "bip9": {
          "status": "active",
          "start_time": 1619222400,
          "timeout": 1628640000,
          "since": 709632,
          "min_activation_height": 709632
        },
        "height": 709632,
        "active": true
      }
    },
    "warnings": ""
  },
  "error": null,
  "id": 1
}

Working Python3 code:
Code:
import requests, json

rpcPort = 8332
rpcUser = '__cookie__'
rpcPassword = 'xxxxx'
serverURL = 'http://' + rpcUser + ':' + rpcPassword + '@localhost:' + str(rpcPort)

headers = {'Content-Type': 'application/json'}
payload = json.dumps({'id': 1, 'method': 'getblockchaininfo', 'jsonrpc': '2.0'})

print(f'serverURL: {serverURL}')
print(f'payload: {payload}')

try:
  response = requests.post(serverURL, headers=headers, data=payload)
  print(response)
  print(response.status_code)
  print(response.reason)

  print(response.text)
except requests.exceptions.HTTPError as e:
  print(e)
  print(e.status_code)
  print(e.reason)

My C++ version which also works fine and just requires that httplib.h file to be downloaded and placed in the same folder:
Code:
#include "./httplib.h"

int main() {
  int rpcPort = 8332;
  const char* rpcUser     = "__cookie__";
  const char* rpcPassword = "8abb90c7902e13105976a94ff5abbc4c9526f745235438bccc8b23aa2d9df0b3";
  std::string serverURL   = "127.0.0.1";
  std::string body        = "{\"id\":1, \"method\":\"getblockchaininfo\", \"jsonrpc\":\"2.0\"}";

  httplib::Client cli(serverURL, rpcPort);
  cli.set_basic_auth(rpcUser, rpcPassword);

  if (auto res = cli.Post("/", body, "application/json")) {
    std::cout << res->status << std::endl;
    std::cout << res->body << std::endl;
  }
  else {
    auto err = res.error();
    std::cout << "Error: " <<  err << std::endl;
  }
}

Code:
$~/test/cppbitcointest> g++ -l:libcrypto.so.1.1 bitcointest.cpp -o bitcointest && ./bitcointest 
200
{"result":{"chain":"main","blocks":729726,"headers":729726,"bestblockhash":"00000000000000000007f5b05ab0ce3816fcf0c6593b3aa11dc062d4ecf3142e","difficulty":27452707696466.39,"mediantime":1648656001,"verificationprogress":0.9999907234912998,"initialblockdownload":false,"chainwork":"00000000000000000000000000000000000000002b2be3f65323c1f032368092","size_on_disk":452447125068,"pruned":false,"softforks":{"bip34":{"type":"buried","active":true,"height":227931},"bip66":{"type":"buried","active":true,"height":363725},"bip65":{"type":"buried","active":true,"height":388381},"csv":{"type":"buried","active":true,"height":419328},"segwit":{"type":"buried","active":true,"height":481824},"taproot":{"type":"bip9","bip9":{"status":"active","start_time":1619222400,"timeout":1628640000,"since":709632,"min_activation_height":709632},"height":709632,"active":true}},"warnings":""},"error":null,"id":1}

I believe the RPC you're looking for is listunspent.
By replacing the body in the above code examples with the following, it should return what you're looking for.
Code:
'{"jsonrpc": "1.0", "id": "curltest", "method": "listunspent", "params": [6, 9999999]}'

█▀▀▀











█▄▄▄
▀▀▀▀▀▀▀▀▀▀▀
e
▄▄▄▄▄▄▄▄▄▄▄
█████████████
████████████▄███
██▐███████▄█████▀
█████████▄████▀
███▐████▄███▀
████▐██████▀
█████▀█████
███████████▄
████████████▄
██▄█████▀█████▄
▄█████████▀█████▀
███████████▀██▀
████▀█████████
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
c.h.
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
▀▀▀█











▄▄▄█
▄██████▄▄▄
█████████████▄▄
███████████████
███████████████
███████████████
███████████████
███░░█████████
███▌▐█████████
█████████████
███████████▀
██████████▀
████████▀
▀██▀▀
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!