From be817f7f8446629bfc133ed47452b4d680492267 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Thu, 15 Aug 2024 03:30:27 -0600 Subject: [PATCH] WIP: p2p begins again --- public/dashjoin.js | 203 +++++++++++++++++++++++++++++++++++++++++++ public/index.html | 2 + public/wallet-app.js | 45 +++++----- 3 files changed, 229 insertions(+), 21 deletions(-) diff --git a/public/dashjoin.js b/public/dashjoin.js index ad2fb67..ecdc195 100644 --- a/public/dashjoin.js +++ b/public/dashjoin.js @@ -2,10 +2,21 @@ var DashJoin = ('object' === typeof module && exports) || {}; (function (window, DashJoin) { 'use strict'; + let DashTx = window.DashTx || require('dashtx'); + + //@ts-ignore + let Packer = window.CJPacker || require('./packer.js'); + //@ts-ignore + let Parser = window.CJParser || require('./parser.js'); + const DENOM_LOWEST = 100001; const PREDENOM_MIN = DENOM_LOWEST + 193; const COLLATERAL = 10000; // DENOM_LOWEST / 10 + // https://github.com/dashpay/dash/blob/v19.x/src/coinjoin/coinjoin.h#L39 + // const COINJOIN_ENTRY_MAX_SIZE = 9; // real + // const COINJOIN_ENTRY_MAX_SIZE = 2; // just for testing right now + DashJoin.DENOM_LOWEST = DENOM_LOWEST; DashJoin.COLLATERAL = COLLATERAL; DashJoin.PREDENOM_MIN = PREDENOM_MIN; @@ -31,6 +42,198 @@ var DashJoin = ('object' === typeof module && exports) || {}; return 0; }; + DashJoin.utils = {}; + + DashJoin.utils.hexToBytes = function (hex) { + let bufLen = hex.length / 2; + let u8 = new Uint8Array(bufLen); + + let i = 0; + let index = 0; + let lastIndex = hex.length - 2; + for (;;) { + if (i > lastIndex) { + break; + } + + let h = hex.slice(i, i + 2); + let b = parseInt(h, 16); + u8[index] = b; + + i += 2; + index += 1; + } + + return u8; + }; + + // { + // let versionP = dj.once('version', { timeout: 1500 }); + // dj.send('version', packVersion()) + // for (;;) { + // versionP = dj.once('version', { timeout: 1500 }); + // let version = await versionP; + // if (version.isTheRightOne) { + // break; + // } + // } + // } + + DashJoin.utils.bytesToHex = function (u8) { + /** @type {Array} */ + let hex = []; + + u8.forEach(function (b) { + let h = b.toString(16).padStart(2, '0'); + hex.push(h); + }); + + return hex.join(''); + }; + + DashJoin.wsConnect = function (p2pWebProxyUrl, evonode) { + if (!p2pWebProxyUrl) { + //p2pWebProxyUrl = 'wss://tp2p.digitalcash.dev/ws'; + p2pWebProxyUrl = 'wss://ubuntu-127.scratch-dev.digitalcash.dev/ws'; + } + + let query = { + access_token: 'secret', + hostname: evonode.hostname, + port: evonode.port, + }; + let searchParams = new URLSearchParams(query); + let search = searchParams.toString(); + let wsc = new WebSocket(`${p2pWebProxyUrl}?${search}`); + + // TODO listen to all messages that are CJ Pool messages + // (and build current pools) + + let dataCount = 0; + wsc.addEventListener('message', async function (wsevent) { + console.log('[DEBUG] onReadableHeader wsc.onmessage'); + let ab = await wsevent.data.arrayBuffer(); + let bytes = new Uint8Array(ab); + dataCount += bytes.length; + console.log('[DEBUG] bytes (readable header)'); + console.log(dataCount, bytes.length, DashJoin.utils.bytesToHex(bytes)); + // onReadableHeader(bytes); + + let currentHeader = Parser.parseHeader(bytes); + console.log(currentHeader); + }); + + return wsc; + }; + + DashJoin.sendVersion = function ( + wsc, + evonode, + blockHeight, + agentVersion, + network, + ) { + // + // version / verack + // + let versionMsg = Packer.version({ + network: network, // Packer.NETWORKS.regtest, + //protocol_version: Packer.PROTOCOL_VERSION, + //addr_recv_services: [Packer.IDENTIFIER_SERVICES.NETWORK], + addr_recv_ip: evonode.hostname, + addr_recv_port: evonode.port, + //addr_trans_services: [], + //addr_trans_ip: '127.0.01', + //addr_trans_port: null, + // addr_trans_ip: conn.localAddress, + // addr_trans_port: conn.localPort, + start_height: blockHeight, + //nonce: null, + user_agent: `DashJoin.js/${agentVersion}`, + // optional-ish + relay: false, + mnauth_challenge: null, + mn_connection: false, + }); + wsc.send(versionMsg); + }; + + DashJoin.utils._evonodeMapToList = function (evonodesMap) { + console.log('[debug] get evonode list...'); + let evonodes = []; + { + //let resp = await rpc.masternodelist(); + let evonodeProTxIds = Object.keys(evonodesMap); + for (let id of evonodeProTxIds) { + let evonode = evonodesMap[id]; + if (evonode.status !== 'ENABLED') { + continue; + } + + let hostParts = evonode.address.split(':'); + let evodata = { + id: evonode.id, + host: evonode.address, + hostname: hostParts[0], + port: hostParts[1], + type: evonode.type, + }; + evonodes.push(evodata); + } + if (!evonodes.length) { + throw new Error('Sanity Fail: no evonodes online'); + } + } + + // void shuffle(evonodes); + evonodes.sort(DashJoin.utils.sortMnListById); + return evonodes; + }; + + /** + * @param {Object} a + * @param {String} a.id + * @param {Object} b + * @param {String} b.id + */ + DashJoin.utils.sortMnListById = function (a, b) { + if (a.id > b.id) { + return 1; + } + if (a.id < b.id) { + return -1; + } + return 0; + }; + + /** + * @param {Array} byteArrays + * @param {Number?} [len] + * @returns {Uint8Array} + */ + function concatBytes(byteArrays, len) { + if (!len) { + for (let bytes of byteArrays) { + len += bytes.length; + } + } + + let allBytes = new Uint8Array(len); + let offset = 0; + for (let bytes of byteArrays) { + allBytes.set(bytes, offset); + offset += bytes.length; + } + + return allBytes; + } + + function sleep(ms) { + return new Promise(function (resolve) { + setTimeout(resolve, ms); + }); + } + //@ts-ignore window.DashJoin = DashJoin; })(globalThis.window || {}, DashJoin); diff --git a/public/index.html b/public/index.html index b5a5b47..5372d42 100644 --- a/public/index.html +++ b/public/index.html @@ -10,6 +10,8 @@ + +