Skip to content

Commit 9535a76

Browse files
authored
Merge pull request #1263 from permaweb/jfrain99/eth-address-rl
fix(mu): allow rl for eth addresses
2 parents d468030 + 4637b39 commit 9535a76

File tree

5 files changed

+91
-10
lines changed

5 files changed

+91
-10
lines changed

servers/mu/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"express": "^4.18.2",
3434
"http-message-signatures": "^1.0.4",
3535
"hyper-async": "^1.1.2",
36+
"keccak": "^3.0.4",
3637
"lru-cache": "^10.2.0",
3738
"node-cron": "^3.0.3",
3839
"p-map": "^7.0.1",

servers/mu/src/config.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,15 +130,15 @@ const CONFIG_ENVS = {
130130
MAX_WORKERS: process.env.MAX_WORKERS || Math.max(cpus().length - 1, 1),
131131
DB_URL: process.env.DB_URL || 'ao-cache',
132132
TRACE_DB_URL: process.env.TRACE_DB_URL || 'trace',
133-
TASK_QUEUE_MAX_RETRIES: process.env.TASK_QUEUE_MAX_RETRIES || 5,
133+
TASK_QUEUE_MAX_RETRIES: 10,
134134
TASK_QUEUE_RETRY_DELAY: process.env.TASK_QUEUE_RETRY_DELAY || 1000,
135135
DISABLE_TRACE: process.env.DISABLE_TRACE !== 'false',
136136
SPAWN_PUSH_ENABLED: process.env.SPAWN_PUSH_ENABLED === 'true',
137137
ALLOW_PUSHES_AFTER: process.env.ALLOW_PUSHES_AFTER || 1580000,
138138
ENABLE_MESSAGE_RECOVERY: process.env.ENABLE_MESSAGE_RECOVERY === 'true',
139139
GET_RESULT_MAX_RETRIES: process.env.GET_RESULT_MAX_RETRIES || 5,
140140
GET_RESULT_RETRY_DELAY: process.env.GET_RESULT_RETRY_DELAY || 1000,
141-
MESSAGE_RECOVERY_MAX_RETRIES: process.env.MESSAGE_RECOVERY_MAX_RETRIES || 17,
141+
MESSAGE_RECOVERY_MAX_RETRIES: 10,
142142
MESSAGE_RECOVERY_RETRY_DELAY: process.env.MESSAGE_RECOVERY_RETRY_DELAY || 1000,
143143
RELAY_MAP: process.env.RELAY_MAP || '',
144144
ENABLE_PUSH: process.env.ENABLE_PUSH === 'true',
@@ -151,7 +151,7 @@ const CONFIG_ENVS = {
151151
HB_ROUTER_URL: process.env.HB_ROUTER_URL || 'https://forward.computer',
152152
ENABLE_HB_WALLET_CHECK: process.env.ENABLE_HB_WALLET_CHECK !== 'false',
153153
HB_GRAPHQL_URL: process.env.HB_GRAPHQL_URL || 'https://cache.forward.computer',
154-
RATE_LIMIT_FILE_URL: process.env.RATE_LIMIT_FILE_URL || ""
154+
RATE_LIMIT_FILE_URL: process.env.RATE_LIMIT_FILE_URL || ''
155155
},
156156
production: {
157157
MODE,
@@ -171,15 +171,15 @@ const CONFIG_ENVS = {
171171
MAX_WORKERS: process.env.MAX_WORKERS || Math.max(cpus().length - 1, 1),
172172
DB_URL: process.env.DB_URL || 'ao-cache',
173173
TRACE_DB_URL: process.env.TRACE_DB_URL || 'trace',
174-
TASK_QUEUE_MAX_RETRIES: process.env.TASK_QUEUE_MAX_RETRIES || 5,
174+
TASK_QUEUE_MAX_RETRIES: 10,
175175
TASK_QUEUE_RETRY_DELAY: process.env.TASK_QUEUE_RETRY_DELAY || 1000,
176176
DISABLE_TRACE: process.env.DISABLE_TRACE !== 'false',
177177
SPAWN_PUSH_ENABLED: process.env.SPAWN_PUSH_ENABLED === 'true',
178178
ALLOW_PUSHES_AFTER: process.env.ALLOW_PUSHES_AFTER || 1580000,
179179
ENABLE_MESSAGE_RECOVERY: process.env.ENABLE_MESSAGE_RECOVERY === 'true',
180180
GET_RESULT_MAX_RETRIES: process.env.GET_RESULT_MAX_RETRIES || 5,
181181
GET_RESULT_RETRY_DELAY: process.env.GET_RESULT_RETRY_DELAY || 1000,
182-
MESSAGE_RECOVERY_MAX_RETRIES: process.env.MESSAGE_RECOVERY_MAX_RETRIES || 17,
182+
MESSAGE_RECOVERY_MAX_RETRIES: 10,
183183
MESSAGE_RECOVERY_RETRY_DELAY: process.env.MESSAGE_RECOVERY_RETRY_DELAY || 1000,
184184
RELAY_MAP: process.env.RELAY_MAP || '',
185185
ENABLE_PUSH: process.env.ENABLE_PUSH === 'true',
@@ -192,7 +192,7 @@ const CONFIG_ENVS = {
192192
HB_ROUTER_URL: process.env.HB_ROUTER_URL || 'https://forward.computer',
193193
ENABLE_HB_WALLET_CHECK: process.env.ENABLE_HB_WALLET_CHECK !== 'false',
194194
HB_GRAPHQL_URL: process.env.HB_GRAPHQL_URL || 'https://cache.forward.computer',
195-
RATE_LIMIT_FILE_URL: process.env.RATE_LIMIT_FILE_URL || ""
195+
RATE_LIMIT_FILE_URL: process.env.RATE_LIMIT_FILE_URL || ''
196196
}
197197
}
198198

servers/mu/src/domain/api/sendDataItem.js

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { of, Rejected, fromPromise, Resolved } from 'hyper-async'
22
import { compose, head, identity, isEmpty, prop, propOr } from 'ramda'
3+
import createKeccakHash from 'keccak'
34

45
import { getCuAddressWith } from '../lib/get-cu-address.js'
56
import { writeMessageTxWith } from '../lib/write-message-tx.js'
@@ -50,6 +51,38 @@ export function sendDataItemWith ({
5051
const insertMessage = insertMessageWith({ db })
5152

5253
const locateProcessLocal = fromPromise(locateProcessSchema.implement(locateProcess))
54+
function keyToEthereumAddress (key) {
55+
/**
56+
* We need to decode, then remove the first byte denoting compression in secp256k1
57+
*/
58+
const noCompressionByte = Buffer.from(key, 'base64url').subarray(1)
59+
60+
/**
61+
* the un-prefixed address is the last 20 bytes of the hashed
62+
* public key
63+
*/
64+
const noPrefix = createKeccakHash('keccak256')
65+
.update(noCompressionByte)
66+
.digest('hex')
67+
.slice(-40)
68+
69+
/**
70+
* Apply the checksum see https://eips.ethereum.org/EIPS/eip-55
71+
*/
72+
const hash = createKeccakHash('keccak256')
73+
.update(noPrefix)
74+
.digest('hex')
75+
76+
let checksumAddress = '0x'
77+
for (let i = 0; i < noPrefix.length; i++) {
78+
checksumAddress += parseInt(hash[i], 16) >= 8
79+
? noPrefix[i].toUpperCase()
80+
: noPrefix[i]
81+
}
82+
83+
return checksumAddress
84+
}
85+
5386
/**
5487
* Check if the rate limit has been exceeded using rate limit injected
5588
*/
@@ -68,7 +101,10 @@ export function sendDataItemWith ({
68101
if (isWhitelisted) return Resolved(ctx)
69102
const intervalStart = new Date().getTime() - IP_WALLET_RATE_LIMIT_INTERVAL
70103
const wallet = ctx.dataItem.owner
71-
const address = await toAddress(wallet) || null
104+
let address = await toAddress(wallet) || null
105+
if (ctx.dataItem.signature.length === 87) {
106+
address = keyToEthereumAddress(ctx.dataItem.owner)
107+
}
72108
const rateLimitAllowance = calculateRateLimit(address, ctx.dataItem.target ?? 'SPAWN', rateLimits)
73109
const recentTraces = await getRecentTraces({ wallet, timestamp: intervalStart, processId: ctx.dataItem.target })
74110
const walletTracesCount = recentTraces.wallet.length
@@ -121,7 +157,8 @@ export function sendDataItemWith ({
121157
assigns,
122158
initialTxId,
123159
parentId,
124-
ip: ctx.ip
160+
ip: ctx.ip,
161+
parentOwner: ctx.dataItem?.owner
125162
})
126163
})
127164
.bimap(

servers/mu/src/domain/clients/taskQueue.js

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import createKeccakHash from 'keccak'
2+
13
import { randomBytes } from 'crypto'
24
import { TASKS_TABLE } from './sqlite.js'
35

@@ -52,6 +54,38 @@ export async function createTaskQueue ({ queueId, logger, db }) {
5254
* be removed from the database when dequeuing.
5355
*/
5456
export function enqueueWith ({ queue, queueId, logger, db, getRecentTraces, toAddress, getRateLimits, IP_WALLET_RATE_LIMIT, IP_WALLET_RATE_LIMIT_INTERVAL, rateLimits }) {
57+
function keyToEthereumAddress (key) {
58+
/**
59+
* We need to decode, then remove the first byte denoting compression in secp256k1
60+
*/
61+
const noCompressionByte = Buffer.from(key, 'base64url').subarray(1)
62+
63+
/**
64+
* the un-prefixed address is the last 20 bytes of the hashed
65+
* public key
66+
*/
67+
const noPrefix = createKeccakHash('keccak256')
68+
.update(noCompressionByte)
69+
.digest('hex')
70+
.slice(-40)
71+
72+
/**
73+
* Apply the checksum see https://eips.ethereum.org/EIPS/eip-55
74+
*/
75+
const hash = createKeccakHash('keccak256')
76+
.update(noPrefix)
77+
.digest('hex')
78+
79+
let checksumAddress = '0x'
80+
for (let i = 0; i < noPrefix.length; i++) {
81+
checksumAddress += parseInt(hash[i], 16) >= 8
82+
? noPrefix[i].toUpperCase()
83+
: noPrefix[i]
84+
}
85+
86+
return checksumAddress
87+
}
88+
5589
async function checkRateLimitExceeded (task) {
5690
function calculateRateLimit (walletID, procID, limits) {
5791
if (!walletID) return 100
@@ -65,7 +99,11 @@ export function enqueueWith ({ queue, queueId, logger, db, getRecentTraces, toAd
6599
const intervalStart = new Date().getTime() - IP_WALLET_RATE_LIMIT_INTERVAL
66100
const wallet = task?.wallet || task?.cachedMsg?.wallet || null
67101
const processId = task?.cachedMsg?.msg?.Target || task?.processId || null
68-
const address = task?.cachedMsg?.cron ? wallet : await toAddress(wallet)
102+
let address = task?.cachedMsg?.cron ? wallet : await toAddress(wallet)
103+
const owner = (task.parentOwner ?? task?.wallet ?? task.cachedMsg?.wallet)
104+
if (owner?.length === 87) {
105+
address = keyToEthereumAddress(owner)
106+
}
69107
const rateLimits = getRateLimits()
70108
const isWhitelisted = (rateLimits?.ips?.[task?.ip] ?? 0) > 1
71109
if (isWhitelisted) return false

servers/mu/src/domain/clients/worker-fn.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ export function processResultWith ({
4242
parentId: propOr(undefined, 'parentId', res),
4343
processId: propOr(undefined, 'processId', res),
4444
wallet: propOr(undefined, 'wallet', res),
45-
ip: propOr(undefined, 'ip', res)
45+
ip: propOr(undefined, 'ip', res),
46+
parentOwner: propOr(undefined, 'parentOwner', res)
4647
})
4748
return of(res)
4849
})
@@ -60,6 +61,7 @@ export function processResultWith ({
6061
*/
6162
export function enqueueResultsWith ({ enqueue }) {
6263
return ({ msgs, spawns, assigns, initialTxId, parentId, processId, ...rest }) => {
64+
console.dir({ m: 'ENQUEUING RESULTS' }, { depth: null })
6365
const results = [
6466
...msgs.map(msg => ({
6567
type: 'MESSAGE',
@@ -70,6 +72,7 @@ export function enqueueResultsWith ({ enqueue }) {
7072
parentId: msg.parentId,
7173
logId: randomBytes(8).toString('hex'),
7274
ip: rest.ip,
75+
parentOwner: rest.parentOwner,
7376
wallet: msg.wallet
7477
})),
7578
...spawns.map(spawn => ({
@@ -81,6 +84,7 @@ export function enqueueResultsWith ({ enqueue }) {
8184
parentId: spawn.parentId,
8285
logId: randomBytes(8).toString('hex'),
8386
ip: rest.ip,
87+
parentOwner: rest.parentOwner,
8488
wallet: spawn.wallet
8589
})),
8690
...assigns.flatMap(assign => assign.Processes.map(
@@ -97,6 +101,7 @@ export function enqueueResultsWith ({ enqueue }) {
97101
parentId,
98102
logId: randomBytes(8).toString('hex'),
99103
ip: rest.ip,
104+
parentOwner: rest.parentOwner,
100105
wallet: rest.wallet ?? null
101106
})
102107
))

0 commit comments

Comments
 (0)