Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1#!/usr/bin/env python32# Copyright (c) 2017-present The Bitcoin Core developers3# Distributed under the MIT software license, see the accompanying4# file COPYING or http://www.opensource.org/licenses/mit-license.php.5"""6A test for RPC users with restricted permissions7"""8from test_framework.test_framework import BitcoinTestFramework9from test_framework.util import (10assert_equal,11str_to_b64str,12)13import http.client14import urllib.parse17def rpccall(node, user, method):18url = urllib.parse.urlparse(node.url)19headers = {"Authorization": "Basic " + str_to_b64str('{}:{}'.format(user[0], user[3]))}20conn = http.client.HTTPConnection(url.hostname, url.port)21conn.connect()22conn.request('POST', '/', '{"method": "' + method + '"}', headers)23resp = conn.getresponse()24conn.close()25return resp28def get_permissions(whitelist):29return [perm for perm in whitelist.split(",") if perm]32class RPCWhitelistTest(BitcoinTestFramework):34def set_test_params(self):35self.num_nodes = 137def run_test(self):38# 0 => Username39# 1 => Password (Hashed)40# 2 => Permissions41# 3 => Password Plaintext42self.users = [43["user1", "50358aa884c841648e0700b073c32b2e$b73e95fff0748cc0b517859d2ca47d9bac1aa78231f3e48fa9222b612bd2083e", "getbestblockhash,getblockcount,", "12345"],44["user2", "8650ba41296f62092377a38547f361de$4620db7ba063ef4e2f7249853e9f3c5c3592a9619a759e3e6f1c63f2e22f1d21", "getblockcount", "54321"]45]46# For exceptions47self.strange_users = [48# Test empty49["strangedude", "62d67dffec03836edd698314f1b2be62$c2fb4be29bb0e3646298661123cf2d8629640979cabc268ef05ea613ab54068d", ":", "s7R4nG3R7H1nGZ"],50["strangedude2", "575c012c7fe4b1e83b9d809412da3ef7$09f448d0acfc19924dd62ecb96004d3c2d4b91f471030dfe43c6ea64a8f658c1", "", "s7R4nG3R7H1nGZ"],51# Test trailing comma52["strangedude3", "23189c561b5975a56f4cf94030495d61$3a2f6aac26351e2257428550a553c4c1979594e36675bbd3db692442387728c0", ":getblockcount,", "s7R4nG3R7H1nGZ"],53# Test overwrite54["strangedude4", "990c895760a70df83949e8278665e19a$8f0906f20431ff24cb9e7f5b5041e4943bdf2a5c02a19ef4960dcf45e72cde1c", ":getblockcount, getbestblockhash", "s7R4nG3R7H1nGZ"],55["strangedude4", "990c895760a70df83949e8278665e19a$8f0906f20431ff24cb9e7f5b5041e4943bdf2a5c02a19ef4960dcf45e72cde1c", ":getblockcount", "s7R4nG3R7H1nGZ"],56# Testing the same permission twice57["strangedude5", "d12c6e962d47a454f962eb41225e6ec8$2dd39635b155536d3c1a2e95d05feff87d5ba55f2d5ff975e6e997a836b717c9", ":getblockcount,getblockcount", "s7R4nG3R7H1nGZ"],58# Test non-whitelisted user59["strangedude6", "67e5583538958883291f6917883eca64$8a866953ef9c5b7d078a62c64754a4eb74f47c2c17821eb4237021d7ef44f991", None, "N4SziYbHmhC1"]60]61# These commands shouldn't be allowed for any user to test failures62self.never_allowed = ["getnetworkinfo"]63with open(self.nodes[0].datadir_path / "bitcoin.conf", "a") as f:64f.write("\nrpcwhitelistdefault=0\n")65for user in self.users:66f.write("rpcauth=" + user[0] + ":" + user[1] + "\n")67f.write("rpcwhitelist=" + user[0] + ":" + user[2] + "\n")68# Special cases69for strangedude in self.strange_users:70f.write("rpcauth=" + strangedude[0] + ":" + strangedude[1] + "\n")71if strangedude[2] is not None:72f.write("rpcwhitelist=" + strangedude[0] + strangedude[2] + "\n")73self.restart_node(0)75for user in self.users:76for permission in self.never_allowed:77self.log.info(f"[{user[0]}]: Testing a non permitted permission ({permission})")78assert_equal(403, rpccall(self.nodes[0], user, permission).status)79# Now test the strange users80for permission in self.never_allowed:81self.log.info("Strange test 1")82assert_equal(403, rpccall(self.nodes[0], self.strange_users[0], permission).status)83for permission in self.never_allowed:84self.log.info("Strange test 2")85assert_equal(403, rpccall(self.nodes[0], self.strange_users[1], permission).status)86self.log.info("Strange test 3")87assert_equal(200, rpccall(self.nodes[0], self.strange_users[2], "getblockcount").status)88self.log.info("Strange test 4")89assert_equal(403, rpccall(self.nodes[0], self.strange_users[3], "getbestblockhash").status)90self.log.info("Strange test 5")91assert_equal(200, rpccall(self.nodes[0], self.strange_users[4], "getblockcount").status)93self.test_users_permissions()94self.test_rpcwhitelistdefault_permissions(0, 200)96# Replace file configurations97self.nodes[0].replace_in_config([("rpcwhitelistdefault=0", "rpcwhitelistdefault=1")])98with open(self.nodes[0].datadir_path / "bitcoin.conf", 'a') as f:99f.write("rpcwhitelist=__cookie__:getblockcount,getblockchaininfo,getmempoolinfo,stop\n")100self.restart_node(0)102self.test_users_permissions()103self.test_rpcwhitelistdefault_permissions(1, 403)105# Ensure that not specifying -rpcwhitelistdefault is the same as106# specifying -rpcwhitelistdefault=1. Only explicitly whitelisted users107# should be allowed.108self.nodes[0].replace_in_config([("rpcwhitelistdefault=1", "")])109self.restart_node(0)110self.test_users_permissions()111self.test_rpcwhitelistdefault_permissions(1, 403)113def test_users_permissions(self):114"""115* Permissions:116(user1): getbestblockhash,getblockcount117(user2): getblockcount118Expected result: * users can only access whitelisted methods119"""120for user in self.users:121permissions = get_permissions(user[2])122for permission in permissions:123self.log.info(f"[{user[0]}]: Testing whitelisted user permission ({permission})")124assert_equal(200, rpccall(self.nodes[0], user, permission).status)125self.log.info(f"[{user[0]}]: Testing non-permitted permission: getblockchaininfo")126assert_equal(403, rpccall(self.nodes[0], user, "getblockchaininfo").status)128def test_rpcwhitelistdefault_permissions(self, default_value, expected_status):129"""130* rpcwhitelistdefault={default_value}131* No Permissions defined132Expected result: strangedude6 (not whitelisted) access is determined by default_value133When default_value=0: expects 200134When default_value=1: expects 403135"""136user = self.strange_users[6] # strangedude6137for permission in ["getbestblockhash", "getblockchaininfo"]:138self.log.info(f"[{user[0]}]: Testing rpcwhitelistdefault={default_value} no specified permission ({permission})")139assert_equal(expected_status, rpccall(self.nodes[0], user, permission).status)142if __name__ == "__main__":143RPCWhitelistTest(__file__).main()
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.