From a1363483a56b0dee342595c8f44ed8fcce7ecca9 Mon Sep 17 00:00:00 2001 From: Richard Moore Date: Wed, 31 Jan 2024 00:22:23 -0500 Subject: [PATCH] Allow long dnsEncode names with optional length parameter (#4543). --- src.ts/_tests/test-hash.ts | 54 +++++++++++++++++++++++++++++++++++++- src.ts/hash/namehash.ts | 12 ++++----- 2 files changed, 59 insertions(+), 7 deletions(-) diff --git a/src.ts/_tests/test-hash.ts b/src.ts/_tests/test-hash.ts index cacd1b72b..27b1cf358 100644 --- a/src.ts/_tests/test-hash.ts +++ b/src.ts/_tests/test-hash.ts @@ -12,7 +12,7 @@ import { loadTests } from "./utils.js" import type { TestCaseNamehash, TestCaseSolidityHash } from "./types.js"; -//import { dnsEncode, isValidName, namehash } from "../index.js"; +import { dnsEncode } from "../index.js"; describe("Tests Namehash", function() { const tests = loadTests("namehash"); @@ -141,6 +141,58 @@ describe("Tests DNS Names", function() { }); */ +interface TestCaseDnsEncode { + name: string; + length?: number; + result?: string; + error?: string; +} + +describe("Test dnsEncode", function() { + + const tests: Array = [ + { name: "ricmoo.com", result: "0x067269636d6f6f03636f6d00" }, + { name: "ricmoo.com", length: 5, error: "exceeds 5 bytes" }, + { + name: "a-very-long-label-without-a-length-override-foo-12345678901234567890", + error: "exceeds 63 bytes" + }, + { + name: "a-very-long-label-with-a-length-override-to-255-foo-12345678901234567890", + length: 255, result: "0x48612d766572792d6c6f6e672d6c6162656c2d776974682d612d6c656e6774682d6f766572726964652d746f2d3235352d666f6f2d313233343536373839303132333435363738393000" + }, + ]; + + for (const test of tests) { + it(`tests dnsEncode: ${ test.name }`, function() { + if (test.error) { + + assert.throws(() => { + let result; + if (test.length != null) { + result = dnsEncode(test.name, test.length); + } else { + result = dnsEncode(test.name); + } + console.log("result", result); + + }, (error) => { + return (isError(error, "INVALID_ARGUMENT") && + error.argument === "name" && error.value === test.name && + error.message.indexOf(test.error || "") >= 0); + }); + + } else { + if (test.length != null) { + assert.equal(dnsEncode(test.name, test.length), test.result, "dnsEncode(name, length)"); + } else { + assert.equal(dnsEncode(test.name), test.result, "dnsEncode(name)"); + } + } + }); + } +}); + describe("Test EIP-191 Personal Message Hash", function() { const tests = [ { diff --git a/src.ts/hash/namehash.ts b/src.ts/hash/namehash.ts index c06202e40..759383ac8 100644 --- a/src.ts/hash/namehash.ts +++ b/src.ts/hash/namehash.ts @@ -85,17 +85,17 @@ export function namehash(name: string): string { * This is used for various parts of ENS name resolution, such * as the wildcard resolution. */ -export function dnsEncode(name: string): string { +export function dnsEncode(name: string, _maxLength?: number): string { + const length = (_maxLength != null) ? _maxLength: 63; + + assertArgument(length <= 255, "DNS encoded label cannot exceed 255", "length", length); + return hexlify(concat(ensNameSplit(name).map((comp) => { - // DNS does not allow components over 63 bytes in length - if (comp.length > 63) { - throw new Error("invalid DNS encoded entry; length exceeds 63 bytes"); - } + assertArgument(comp.length <= length, `label ${ JSON.stringify(name) } exceeds ${ length } bytes`, "name", name); const bytes = new Uint8Array(comp.length + 1); bytes.set(comp, 1); bytes[0] = bytes.length - 1; return bytes; - }))) + "00"; }