diff --git a/lib/node/rpc.js b/lib/node/rpc.js index 905e84dae..6871924bf 100644 --- a/lib/node/rpc.js +++ b/lib/node/rpc.js @@ -604,6 +604,8 @@ class RPC extends RPCBase { if (help || args.length !== 0) throw new RPCError(errs.MISC_ERROR, 'getblockchaininfo'); + const sizes = await this.getBlockchainSizes(); + return { chain: this.network.type !== 'testnet' ? this.network.type @@ -621,7 +623,85 @@ class RPC extends RPCBase { deflationary: this.chain.height >= this.network.deflationHeight, pruneheight: this.chain.options.prune ? Math.max(0, this.chain.height - this.network.block.keepBlocks) - : null + : null, + size_on_disk: sizes.blockchain, + sizes: sizes + }; + } + + async getBlockchainSizes() { + const fs = require('bfile'); + const path = require('path'); + + /** + * Get directory size recursively + * @param {String} dirPath - Directory path + * @returns {Promise} - Size in bytes + */ + async function getDirectorySize(dirPath) { + let totalSize = 0; + + try { + const stat = await fs.stat(dirPath); + + if (!stat.isDirectory()) { + return stat.size; + } + + const items = await fs.readdir(dirPath); + + for (const item of items) { + const itemPath = path.join(dirPath, item); + const itemStat = await fs.stat(itemPath); + + if (itemStat.isDirectory()) { + totalSize += await getDirectorySize(itemPath); + } else { + totalSize += itemStat.size; + } + } + } catch (e) { + // Directory doesn't exist or can't be accessed + return 0; + } + + return totalSize; + } + + const prefix = this.chain.options.prefix; + const spv = this.chain.options.spv; + + let blockchain = 0; + let tree = 0; + let total = 0; + + // Calculate blockchain size (blocks + chain or spvchain) + if (spv) { + // SPV mode: only spvchain directory + const spvchainPath = path.join(prefix, 'spvchain'); + blockchain = await getDirectorySize(spvchainPath); + } else { + // Full node: blocks + chain directories + const blocksPath = path.join(prefix, 'blocks'); + const chainPath = path.join(prefix, 'chain'); + + blockchain = await getDirectorySize(blocksPath) + + await getDirectorySize(chainPath); + } + + // Calculate tree size (not included in size_on_disk for full nodes) + if (!spv) { + const treePath = path.join(prefix, 'tree'); + tree = await getDirectorySize(treePath); + } + + // Calculate total size blockchain + tree + total = blockchain + tree; + + return { + blockchain: blockchain, + tree: tree, + total: total }; } diff --git a/test/node-rpc-test.js b/test/node-rpc-test.js index 9701d4398..646e69c50 100644 --- a/test/node-rpc-test.js +++ b/test/node-rpc-test.js @@ -54,6 +54,17 @@ describe('RPC', function() { assert.strictEqual(info.blocks, 0); assert.strictEqual(info.headers, 0); assert.strictEqual(info.pruned, false); + + // Check new size fields + assert(typeof info.size_on_disk === 'number'); + assert(info.size_on_disk >= 0); + assert(info.sizes); + assert(typeof info.sizes.blockchain === 'number'); + assert(typeof info.sizes.tree === 'number'); + assert(typeof info.sizes.total === 'number'); + assert(info.sizes.blockchain >= 0); + assert(info.sizes.tree >= 0); + assert(info.sizes.total >= 0); }); });