From 511d5e6d6d0772a2fb9a1f68d3f8f14c61661803 Mon Sep 17 00:00:00 2001 From: David C Goldenberg Date: Tue, 13 May 2025 17:01:18 -0400 Subject: [PATCH] Update. Added validation in the ETH/TRX conversion op, along with many more tests for numerous ops. Finalized the QA. --- src/core/lib/Bitcoin.mjs | 7 ++- src/core/operations/ETHTRXConversion.mjs | 43 ++++++++++++----- tests/operations/tests/ETHTRXConversion.mjs | 48 +++++++++++++++++++ .../tests/PublicKeyToETHStyleAddress.mjs | 36 ++++++++++++++ .../tests/PublicKeyToP2PKHAddress.mjs | 11 +++++ .../tests/PublicKeyToTRXStyleAddress.mjs | 47 ++++++++++++++++++ 6 files changed, 178 insertions(+), 14 deletions(-) diff --git a/src/core/lib/Bitcoin.mjs b/src/core/lib/Bitcoin.mjs index 0cdb21d7..c65699d7 100644 --- a/src/core/lib/Bitcoin.mjs +++ b/src/core/lib/Bitcoin.mjs @@ -198,7 +198,12 @@ export function liftX(input) { const pHex ="0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"; const p = BigNumber(pHex, 16); - const x = BigNumber("0x" + makeSureIsHex(input), 16); + let x; + try { + x = BigNumber("0x" + makeSureIsHex(input), 16); + } catch (TypeError) { + return -1; + } if (x.comparedTo(p) === 1) { return -1; } else { diff --git a/src/core/operations/ETHTRXConversion.mjs b/src/core/operations/ETHTRXConversion.mjs index 67f97f1e..57218c9b 100644 --- a/src/core/operations/ETHTRXConversion.mjs +++ b/src/core/operations/ETHTRXConversion.mjs @@ -5,7 +5,7 @@ */ import Operation from "../Operation.mjs"; -import {base58Decode, base58Encode, doubleSHA} from "../lib/Bitcoin.mjs"; +import {base58Decode, base58Encode, doubleSHA, b58DoubleSHAChecksum} from "../lib/Bitcoin.mjs"; import Utils from "../Utils.mjs"; import {toHex} from "crypto-api/src/encoder/hex.mjs"; import { fromArrayBuffer } from "crypto-api/src/encoder/array-buffer.mjs"; @@ -35,6 +35,24 @@ function ethCheckSum(address) { return "0x" + finalResult; } +/** + * Checks if past in address could be a valid ETH address based off of regex. + * @param {*} input + * @returns + */ +function validateETHAddress(input) { + const regex = /^0x[a-f,A-F,0-9]{40}$/g; + return regex.test(input); +} + +/** + * Runs the checksum on the potential TRX address. Returns false is checksum fails. + * @param {*} input + * @returns + */ +function validateTRXAddress(input) { + return b58DoubleSHAChecksum(input); +} /** * ETH / TRX Conversion operation */ @@ -58,18 +76,6 @@ class ETHTRXConversion extends Operation { type: "option", value: ["ETH->TRX", "TRX->ETH"] } - /* Example arguments. See the project wiki for full details. - { - name: "First arg", - type: "string", - value: "Don't Panic" - }, - { - name: "Second arg", - type: "number", - value: 42 - } - */ ]; } @@ -80,8 +86,16 @@ class ETHTRXConversion extends Operation { */ run(input, args) { const [direction] = args; + // We check if input is blank. + // If its blank or just whitespace, we don't need to bother dealing with it. + if (input.trim().length === 0) { + return ""; + } switch (direction) { case "ETH->TRX":{ + if (!validateETHAddress(input)) { + return "Invalid ETH address. ETH addresses should have 20 bytes (40 characters) prefaced by 0x."; + } const unencodedAddress = input.slice(2,); const checksumHash = toHex(doubleSHA(fromArrayBuffer(Utils.convertToByteArray("41" + unencodedAddress, "hex")))); const finalString = "41" + unencodedAddress + checksumHash.slice(0, 8); @@ -89,6 +103,9 @@ class ETHTRXConversion extends Operation { return address; } case "TRX->ETH":{ + if (!validateTRXAddress(input)) { + return "Invalid TRX Address. Checksum failed."; + } return ethCheckSum("0x" + toHex(fromArrayBuffer(base58Decode(input).slice(1, -4)))); } diff --git a/tests/operations/tests/ETHTRXConversion.mjs b/tests/operations/tests/ETHTRXConversion.mjs index 3cc368d0..de9e9cdf 100644 --- a/tests/operations/tests/ETHTRXConversion.mjs +++ b/tests/operations/tests/ETHTRXConversion.mjs @@ -20,6 +20,30 @@ TestRegister.addTests([ }, ], + }, + { + name: "ETH To TRX (Invalid ETH)", + input: "0xAb495f468B0bF116860E76be9f26339b2CbC33c3x", + expectedOutput: "Invalid ETH address. ETH addresses should have 20 bytes (40 characters) prefaced by 0x.", + recipeConfig: [ + { + "op": "ETH / TRX Conversion", + "args": ["ETH->TRX"] + }, + ], + + }, + { + name: "ETH To TRX (Blank Input)", + input: "", + expectedOutput: "", + recipeConfig: [ + { + "op": "ETH / TRX Conversion", + "args": ["ETH->TRX"] + }, + ], + }, { name: "TRX to ETH", @@ -32,6 +56,30 @@ TestRegister.addTests([ }, ], + }, + { + name: "TRX to ETH (Invalid TRX by Length)", + input: "TRatSrEqUKLK4eNWL8NSrvEbpeht5takWde", + expectedOutput: "Invalid TRX Address. Checksum failed.", + recipeConfig: [ + { + "op": "ETH / TRX Conversion", + "args": ["TRX->ETH"] + }, + ], + + }, + { + name: "TRX to ETH (Invalid TRX by Character Substitution)", + input: "TRatSrEqUKLK4eNLL8NSrvEbpeht5takWd", + expectedOutput: "Invalid TRX Address. Checksum failed.", + recipeConfig: [ + { + "op": "ETH / TRX Conversion", + "args": ["TRX->ETH"] + }, + ], + }, { name: "TRX to ETH With Checksum", diff --git a/tests/operations/tests/PublicKeyToETHStyleAddress.mjs b/tests/operations/tests/PublicKeyToETHStyleAddress.mjs index 81c509c2..f0397831 100644 --- a/tests/operations/tests/PublicKeyToETHStyleAddress.mjs +++ b/tests/operations/tests/PublicKeyToETHStyleAddress.mjs @@ -33,6 +33,18 @@ TestRegister.addTests([ }, ], + }, + { + name: "Public Key To ETH Style Address Invalid Uncompressed Key", + input: "027d3e5107b46421c3ddf7292fcbe1f5805952279926c325d119f6ddfed1e5e7ea9a9f5dceadc57b897cb286479450b66a6422f8f270bcd2a61ab4eea800911956", + expectedOutput: "We have a valid hex string of reasonable length, (130) but doesn't start with the right value. Correct values are 04 but we have: 02", + recipeConfig: [ + { + "op": "Public Key To ETH Style Address", + "args": [] + }, + ], + }, { name: "Public Key to ETH Style Address: Compressed Key", @@ -45,6 +57,30 @@ TestRegister.addTests([ }, ], + }, + { + name: "Public Key to ETH Style Address: Blank Input", + input: "", + expectedOutput: "", + recipeConfig: [ + { + "op": "Public Key To ETH Style Address", + "args": [] + }, + ], + + }, + { + name: "Public Key to ETH Style Address: Invalid Compressed Key", + input: "059d491d3f5a2a79b422b76b8115b175b38e42c6103b1a84c88fb6221fe9072bbe", + expectedOutput: "We have a valid hex string, of reasonable length, (66) but doesn't start with the right value. Correct values are 02, or 03 but we have: 05", + recipeConfig: [ + { + "op": "Public Key To ETH Style Address", + "args": [], + }, + ], + }, { name: "Public Key to ETH Style Address: Compressed Key 2", diff --git a/tests/operations/tests/PublicKeyToP2PKHAddress.mjs b/tests/operations/tests/PublicKeyToP2PKHAddress.mjs index ced9881a..c92935f2 100644 --- a/tests/operations/tests/PublicKeyToP2PKHAddress.mjs +++ b/tests/operations/tests/PublicKeyToP2PKHAddress.mjs @@ -10,6 +10,17 @@ import TestRegister from "../../lib/TestRegister.mjs"; TestRegister.addTests([ + { + name: "Public Key To Address: P2PKH (Empty String)", + input: "", + expectedOutput: "", + recipeConfig: [ + { + "op": "Public Key To Bitcoin-Like Address", + "args": ["BTC", "P2PKH (V1 BTC Addresses)"] + }, + ], + }, { name: "Public Key To Address: P2PKH (1)", input: "03ebf60a619da2fbc6239089ca0a93878ea53baa3d22188cacad4033b103237ae9", diff --git a/tests/operations/tests/PublicKeyToTRXStyleAddress.mjs b/tests/operations/tests/PublicKeyToTRXStyleAddress.mjs index 47bf4dd8..334e62fd 100644 --- a/tests/operations/tests/PublicKeyToTRXStyleAddress.mjs +++ b/tests/operations/tests/PublicKeyToTRXStyleAddress.mjs @@ -10,6 +10,17 @@ import TestRegister from "../../lib/TestRegister.mjs"; TestRegister.addTests([ + { + name: "Public Key To TRX Style Address, Invalid Uncompressed.", + input: "05187ac6bc2723630c936e363b826de17dac62382e3bbfabf306ad5f55cc79538783889fe32946b52092dad24c56893d522413d67e62b28f6c54f14821367a9edc", + expectedOutput: "We have a valid hex string of reasonable length, (130) but doesn't start with the right value. Correct values are 04 but we have: 05", + recipeConfig: [ + { + "op": "Public Key To TRX Style Address", + "args": [] + }, + ], + }, { name: "Public Key To TRX Style Address", input: "04187ac6bc2723630c936e363b826de17dac62382e3bbfabf306ad5f55cc79538783889fe32946b52092dad24c56893d522413d67e62b28f6c54f14821367a9edc", @@ -33,6 +44,42 @@ TestRegister.addTests([ }, ], + }, + { + name: "Public Key To TRX Style Address Invalid Compressed Key (Length)", + input: "02d1b5855d3f99c4449eb7af576bec1b9bc0bf0769446820686d2de5c47c13b1a0ff", + expectedOutput: "Invalid length. We want either 33, 65 (if bytes) or 66, 130 (if hex) but we got: 68", + recipeConfig: [ + { + "op": "Public Key To TRX Style Address", + "args": [] + }, + ], + + }, + { + name: "Public Key To TRX Style Address (Empty String)", + input: "", + expectedOutput: "", + recipeConfig: [ + { + "op": "Public Key To TRX Style Address", + "args": [] + }, + ], + + }, + { + name: "Public Key To TRX Style Address Invalid Compressed Key", + input: "06d1b5855d3f99c4449eb7af576bec1b9bc0bf0769446820686d2de5c47c13b1a0", + expectedOutput: "We have a valid hex string, of reasonable length, (66) but doesn't start with the right value. Correct values are 02, or 03 but we have: 06", + recipeConfig: [ + { + "op": "Public Key To TRX Style Address", + "args": [] + }, + ], + }, { name: "Public Key to ETH Style Address: Compressed Key 2",