From aac4a10e5525e938ce8caeb920d737686deae2d9 Mon Sep 17 00:00:00 2001 From: Duddino Date: Wed, 12 Jul 2023 00:57:39 +0200 Subject: [PATCH] Add tor masternodes (#149) * Add tor masternodes * comment * Tor v3 support --------- Co-authored-by: JSKitty --- package-lock.json | 23 +++++++++++++++++++++++ package.json | 1 + scripts/global.js | 11 +++++++---- scripts/masternode.js | 40 ++++++++++++++++++++++++++++++++-------- webpack.common.js | 3 +++ 5 files changed, 66 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index d0a816061..97b7f8cab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "@noble/hashes": "^1.1.5", "@noble/secp256k1": "^1.7.0", "@popperjs/core": "^2.11.6", + "base32": "^0.0.7", "bech32": "^2.0.0", "biginteger": "^1.0.3", "bip39": "^3.0.4", @@ -1291,6 +1292,20 @@ "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" }, + "node_modules/base32": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/base32/-/base32-0.0.7.tgz", + "integrity": "sha512-ire9Jmh+BsUk4Idu0wu6aKeJJr/2j28Mlu0qqJBd1SyOGxW/VRotkfwAv3/KE/entVlNwCefs9bxi7kBeCIxTQ==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "base32": "bin/base32.js" + }, + "engines": { + "node": ">0.10" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -5117,6 +5132,14 @@ "node": "*" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", diff --git a/package.json b/package.json index de4711e85..c1f1d643e 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "@noble/hashes": "^1.1.5", "@noble/secp256k1": "^1.7.0", "@popperjs/core": "^2.11.6", + "base32": "^0.0.7", "bech32": "^2.0.0", "biginteger": "^1.0.3", "bip39": "^3.0.4", diff --git a/scripts/global.js b/scripts/global.js index 140ba1842..73a35d9e2 100644 --- a/scripts/global.js +++ b/scripts/global.js @@ -1259,20 +1259,23 @@ export async function destroyMasternode() { /** * Takes an ip address and adds the port. + * If it's a tor address, ip.onion:port will be used (e.g. expyuzz4wqqyqhjn.onion:12345) * If it's an IPv4 address, ip:port will be used, (e.g. 127.0.0.1:12345) * If it's an IPv6 address, [ip]:port will be used, (e.g. [::1]:12345) * @param {String} ip - Ip address with or without port * @returns {String} */ function parseIpAddress(ip) { - // IPv4 without port - if (ip.match(/\d+\.\d+\.\d+\.\d+/)) { + // IPv4 or tor without port + if (ip.match(/\d+\.\d+\.\d+\.\d+/) || ip.match(/\w+\.onion/)) { return `${ip}:${cChainParams.current.MASTERNODE_PORT}`; } - // IPv4 with port - if (ip.match(/\d+\.\d+\.\d+\.\d+:\d+/)) { + + // IPv4 or tor with port + if (ip.match(/\d+\.\d+\.\d+\.\d+:\d+/) || ip.match(/\w+\.onion:\d+/)) { return ip; } + // IPv6 without port if (Address6.isValid(ip)) { return `[${ip}]:${cChainParams.current.MASTERNODE_PORT}`; diff --git a/scripts/masternode.js b/scripts/masternode.js index 24b99b211..876054a8e 100644 --- a/scripts/masternode.js +++ b/scripts/masternode.js @@ -12,6 +12,7 @@ import { Address6 } from 'ip-address'; import * as nobleSecp256k1 from '@noble/secp256k1'; import { OP } from './script.js'; import bs58 from 'bs58'; +import base32 from 'base32'; /** * Construct a Masternode @@ -74,18 +75,41 @@ export default class Masternode { } /** - * @param {String} ip - * @param {Number} port + * @param {string} ip + * @param {number} port * @returns {string} hex representation of the IP + port pair */ static _decodeIpAddress(ip, port) { - const address = ip.includes('.') - ? Address6.fromAddress4(ip) - : new Address6(ip); - const bytes = address.toUnsignedByteArray(); + /** + * @type {Array?} + */ + let bytes; + if (ip.endsWith('.onion')) { + const onionBytes = base32 + .decode(ip.slice(0, -6)) + .split('') + .map((c) => c.charCodeAt(0)); + switch (onionBytes.length) { + case 10: + bytes = [0xfd, 0x87, 0xd8, 0x7e, 0xeb, 0x43, ...onionBytes]; + break; + case 35: + bytes = [0x04, 32, ...onionBytes.slice(0, 32)]; + break; + default: + throw new Error('Invalid onion address'); + } + } else { + const address = ip.includes('.') + ? Address6.fromAddress4(ip) + : new Address6(ip); + bytes = address.toUnsignedByteArray(); + } const res = - bytesToHex([...new Array(16 - bytes.length).fill(0), ...bytes]) + - bytesToHex(Masternode._numToBytes(port, 2, false)); + bytesToHex([ + ...new Array(Math.max(16 - bytes.length, 0)).fill(0), + ...bytes, + ]) + bytesToHex(Masternode._numToBytes(port, 2, false)); return res; } diff --git a/webpack.common.js b/webpack.common.js index 97b4f440c..f71cc7830 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -41,6 +41,9 @@ module.exports = { alias: { 'bn.js': path.join(__dirname, 'node_modules/bn.js/lib/bn.js'), }, + fallback: { + fs: false, + }, }, plugins: [ new HtmlWebpackPlugin({