Skip to content

Commit

Permalink
txt record decoder (#4)
Browse files Browse the repository at this point in the history
* add txt record extract util, update logger for latest server-analytics changes

* lint

* update decoder fn

* update analytics library, and typing

* update action config

* update actions module

* test on node 21

* upload logs as artifacts on failure

* update artifact uploader version

* remove node 20 due to hardhat incompatibility
  • Loading branch information
mdtanrikulu authored Sep 25, 2024
1 parent c0f0aaa commit 7f71305
Show file tree
Hide file tree
Showing 7 changed files with 613 additions and 458 deletions.
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/[email protected]
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

0 comments on commit 7f71305

Please sign in to comment.