Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

txt record decoder #4

Merged
merged 10 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node: ['16.7.x', '18.x']
node: ['18.x', '20.x']
os: [ubuntu-latest, windows-latest, macOS-latest]

steps:
Expand Down
56 changes: 40 additions & 16 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
matrix:
node: ['16.7.x', '18.15.x']
node: ['18.x']
os: [ubuntu-latest, macOS-latest]

steps:
Expand All @@ -38,26 +38,50 @@ jobs:
path: './contracts'
ref: '6b9aaae963f71792ab1a75de61d5151ff1d1b7e3'

# - name: Run local node on Windows
# if: runner.os == 'Windows'
# run: cd contracts; yarn --network-timeout 100000; $env:HARDHAT_DISABLE_TELEMETRY_PROMPT = "true"; $currentDir = (Get-Location).Path; $job = Start-Job -ScriptBlock { param($dir) Set-Location -Path $dir; npx hardhat node --hostname '127.0.0.1' } -ArgumentList $currentDir; Start-Sleep -Seconds 50; Receive-Job -Job $job -Keep
# env:
# BATCH_GATEWAY_URLS: '["https://universal-offchain-unwrapper.ens-cf.workers.dev/"]'
# DOH_GATEWAY_URL: 'https://cloudflare-dns.com/dns-query'

- name: Run local node on Unix
if: runner.os != 'Windows'
run: cd ./contracts && yarn && npx hardhat node --hostname 127.0.0.1 &
- name: Run local node
run: |
cd ./contracts
yarn
npx hardhat node --hostname 127.0.0.1 > hardhat_output.log 2>&1 &
echo $! > hardhat_pid.txt
env:
BATCH_GATEWAY_URLS: '["https://universal-offchain-unwrapper.ens-cf.workers.dev/"]'
DOH_GATEWAY_URL: 'https://cloudflare-dns.com/dns-query'

- name: Wait for local node
uses: iFaxity/wait-on-action@v1.1.0
with:
timeout: 900000
window: 2000
resource: http://127.0.0.1:8545
run: |
timeout=300
while true; do
if [ $timeout -le 0 ]; then
echo "Timeout waiting for Hardhat node"
cat hardhat_output.log
exit 1
fi
if nc -z localhost 8545 2>/dev/null; then
echo "Hardhat node is up and running"
break
fi
echo "Waiting for Hardhat node... ($timeout seconds left)"
sleep 5
timeout=$((timeout - 5))
done
shell: bash

- name: Test
run: yarn test --ci --coverage --maxWorkers=2

- name: Upload Hardhat logs on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: hardhat-logs
path: ./contracts/hardhat_output.log

- name: Cleanup Hardhat process
if: always()
run: |
if [ -f ./contracts/hardhat_pid.txt ]; then
pid=$(cat ./contracts/hardhat_pid.txt)
kill $pid 2>/dev/null || true
fi
shell: bash
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
.DS_Store
.dev.vars
.env
.wrangler
node_modules
coverage
dist
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
}
],
"devDependencies": {
"@cloudflare/workers-types": "^4.20240117.0",
"@cloudflare/workers-types": "^4.20240909.0",
"@ensdomains/ens-contracts": "^0.0.21",
"@types/chai": "^4.3.4",
"@types/chai-as-promised": "^7.1.5",
Expand All @@ -70,18 +70,18 @@
"tsdx": "^0.14.1",
"tslib": "^2.5.0",
"typescript": "^4.9.5",
"wrangler": "^2.0.7"
"wrangler": "^3.78.2"
},
"dependencies": {
"@chainlink/ccip-read-server": "^0.2.1",
"@ensdomains/ccip-read-cf-worker": "^0.0.3",
"@ensdomains/dnsprovejs": "^0.4.1",
"@ensdomains/server-analytics": "^0.0.1-alpha.2",
"@ensdomains/server-analytics": "^0.0.1",
"dotenv": "^16.0.3",
"ethers": "^5.7.2",
"node-fetch": "2.6.1"
},
"volta": {
"node": "16.15.1"
"node": "20.17.0"
}
}
38 changes: 38 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,41 @@ export function serializeError(error: any) {
return JSON.stringify(error);
}
}

type DNSRecord = {
rrset: string;
sig: string;
};

function hexToAscii(hex: string): string {
let result = '';
for (let i = 0; i < hex.length; i += 2) {
const part = parseInt(hex.substring(i, i + 2), 16);
if (part) result += String.fromCharCode(part);
}
return result;
}

export function extractENSRecord(dnsRecords: DNSRecord[]): string[] {
const txtPrefix = '0x0010'; // 16
const txtRecords: string[] = [];

for (const record of dnsRecords) {
if (record.rrset.startsWith(txtPrefix)) {
const contentStart = txtPrefix.length;
const rawContent = record.rrset.slice(contentStart);
let asciiContent = hexToAscii(rawContent);

asciiContent = asciiContent.split('\t').join();

const parts = asciiContent.split(',');
for (const part of parts) {
if (part.includes('ENS1')) {
txtRecords.push(part.slice(2));
}
}
}
}

return txtRecords;
}
60 changes: 36 additions & 24 deletions src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,33 @@ import {
ExecutionContext,
} from '@cloudflare/workers-types';
import { Server } from '@ensdomains/ccip-read-cf-worker';
import { Tracker } from '@ensdomains/server-analytics';
import { PropsDecoder, Tracker } from '@ensdomains/server-analytics';
import { dohQuery } from '@ensdomains/dnsprovejs';
import { ethers } from 'ethers';
import { makeApp } from './app';
import { extractENSRecord } from './utils';

interface ENV {
DOH_GATEWAY_URL: string;
PLAUSIBLE_BASE_URL: string;
}

const tracker = new Tracker('ccip-read-dns-worker.ens-cf.workers.dev', {
enableLogging: true,
});
const abi_RRSetWithSignature = [
ethers.utils.ParamType.from({
components: [
{ type: 'bytes', name: 'rrset' },
{ type: 'bytes', name: 'sig' },
],
type: 'tuple[]',
}),
];

const tracker = new Tracker<CFWRequest>(
'ccip-read-dns-worker.ens-cf.workers.dev',
{
enableLogging: true,
}
);

const routeHandler = (env: ENV, trackEvent?: Function) => {
const { DOH_GATEWAY_URL } = env;
Expand All @@ -28,26 +43,21 @@ const routeHandler = (env: ENV, trackEvent?: Function) => {
return app;
};

const logResult = async (request: CFWRequest, result: Response) => {
if (!result.body) {
return result;
}
const [streamForLog, streamForResult] = result.body.tee();
try {
const resultForLog: { data: string } = await new Response(
streamForLog
).json();
const propsDecoder: PropsDecoder<CFWRequest> = (
_: CFWRequest | unknown,
data?: string
) => {
if (!data) return {};

await tracker.trackEvent(
request,
'result',
{ props: { result: resultForLog.data.substring(0, 200) } },
true
);
} catch (error) {
console.log('error logging result:', error);
}
return new Response(streamForResult, result);
const decodedData = ethers.utils.defaultAbiCoder.decode(
abi_RRSetWithSignature,
data
)[0];
const structuredData = decodedData.map((item: string[]) => ({
rrset: item[0],
sig: item[1],
}));
return { result: extractENSRecord(structuredData) };
};

module.exports = {
Expand All @@ -62,6 +72,8 @@ module.exports = {
await tracker.trackEvent(request, 'request', {}, true);
await tracker.trackPageview(request, {}, true);
const router = routeHandler(env, tracker.trackEvent.bind(tracker, request));
return router.handle(request).then(logResult.bind(this, request));
return router
.handle(request)
.then(tracker.logResult.bind(this, propsDecoder, request));
},
};
Loading
Loading