Skip to content

Commit

Permalink
Merge pull request #766 from permaweb/jfrain99/allow-checkpoint-owner…
Browse files Browse the repository at this point in the history
…-config

feat(cu): allow checkpoint onwer to be configurable #758
  • Loading branch information
jfrain99 authored Jun 6, 2024
2 parents 01b6fd0 + dac3b37 commit 3a8ef59
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 20 deletions.
3 changes: 2 additions & 1 deletion servers/cu/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,10 @@ There are a few environment variables that you can set. Besides
- `RESTRICT_PROCESSES`: A list of process ids that the CU should restrict aka. a
`blacklist` (defaults to none)
- `ALLOW_PROCESSES`: The counterpart to RESTRICT_PROCESSES. When configured the
CU will only execute these processes aka. a `whitelist` (defaults to allow all processes)
CU will only execute these processes aka. a `whitelist` (defaults to allow all processes)
- `ALLOW_OWNERS`: A list of process owners, whose processes are allowed to execute
on the CU aka. an owner `whitelist` (defaults to allow all owners)
- `PROCESS_CHECKPOINT_TRUSTED_OWNERS`: A list of wallets whose checkpoints are trusted and the CU can start from

## Tests

Expand Down
2 changes: 2 additions & 0 deletions servers/cu/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ const CONFIG_ENVS = {
WASM_BINARY_FILE_DIRECTORY: process.env.WASM_BINARY_FILE_DIRECTORY || tmpdir(),
PROCESS_IGNORE_ARWEAVE_CHECKPOINTS: process.env.PROCESS_IGNORE_ARWEAVE_CHECKPOINTS || [],
IGNORE_ARWEAVE_CHECKPOINTS: process.env.IGNORE_ARWEAVE_CHECKPOINTS || [],
PROCESS_CHECKPOINT_TRUSTED_OWNERS: process.env.IGNORE_ARWEAVE_CHECKPOINTS || [],
PROCESS_CHECKPOINT_FILE_DIRECTORY: process.env.PROCESS_CHECKPOINT_FILE_DIRECTORY || tmpdir(),
PROCESS_MEMORY_CACHE_MAX_SIZE: process.env.PROCESS_MEMORY_CACHE_MAX_SIZE || bytes('500mb'),
PROCESS_MEMORY_CACHE_TTL: process.env.PROCESS_MEMORY_CACHE_TTL || ms('24h'),
Expand Down Expand Up @@ -170,6 +171,7 @@ const CONFIG_ENVS = {
WASM_BINARY_FILE_DIRECTORY: process.env.WASM_BINARY_FILE_DIRECTORY || tmpdir(),
PROCESS_IGNORE_ARWEAVE_CHECKPOINTS: process.env.PROCESS_IGNORE_ARWEAVE_CHECKPOINTS || [],
IGNORE_ARWEAVE_CHECKPOINTS: process.env.IGNORE_ARWEAVE_CHECKPOINTS || [],
PROCESS_CHECKPOINT_TRUSTED_OWNERS: process.env.IGNORE_ARWEAVE_CHECKPOINTS || [],
PROCESS_CHECKPOINT_FILE_DIRECTORY: process.env.PROCESS_CHECKPOINT_FILE_DIRECTORY || tmpdir(),
PROCESS_MEMORY_CACHE_MAX_SIZE: process.env.PROCESS_MEMORY_CACHE_MAX_SIZE || bytes('500mb'),
PROCESS_MEMORY_CACHE_TTL: process.env.PROCESS_MEMORY_CACHE_TTL || ms('24h'),
Expand Down
28 changes: 18 additions & 10 deletions servers/cu/src/domain/client/ao-process.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Readable } from 'node:stream'
import { basename, join } from 'node:path'

import { fromPromise, of, Rejected, Resolved } from 'hyper-async'
import { add, always, applySpec, compose, defaultTo, evolve, filter, head, identity, map, omit, path, pathOr, pipe, prop, transduce } from 'ramda'
import { add, always, applySpec, compose, defaultTo, evolve, filter, head, identity, ifElse, isEmpty, map, omit, path, pathOr, pipe, prop, transduce } from 'ramda'
import { z } from 'zod'
import { LRUCache } from 'lru-cache'
import AsyncLock from 'async-lock'
Expand Down Expand Up @@ -476,6 +476,7 @@ export function findLatestProcessMemoryWith ({
loadTransactionData,
PROCESS_IGNORE_ARWEAVE_CHECKPOINTS,
IGNORE_ARWEAVE_CHECKPOINTS,
PROCESS_CHECKPOINT_TRUSTED_OWNERS,
logger: _logger
}) {
const logger = _logger.child('ao-process:findLatestProcessMemory')
Expand All @@ -492,7 +493,7 @@ export function findLatestProcessMemoryWith ({

const GET_AO_PROCESS_CHECKPOINTS = `
query GetAoProcessCheckpoints(
$owner: String!
$owners: [String!]!
$processId: String!
$limit: Int!
) {
Expand All @@ -502,7 +503,7 @@ export function findLatestProcessMemoryWith ({
{ name: "Type", values: ["Checkpoint"] }
{ name: "Data-Protocol", values: ["ao"] }
],
owners: [$owner]
owners: $owners,
first: $limit,
sort: HEIGHT_DESC
) {
Expand Down Expand Up @@ -731,13 +732,20 @@ export function findLatestProcessMemoryWith ({
return Rejected(args)
}

return address()
.chain((owner) => queryCheckpoints({
query: GET_AO_PROCESS_CHECKPOINTS,
variables: { owner, processId, limit: 50 },
processId,
before: LATEST
}))
return of({ PROCESS_CHECKPOINT_TRUSTED_OWNERS })
.chain(({ PROCESS_CHECKPOINT_TRUSTED_OWNERS }) => {
if (isEmpty(PROCESS_CHECKPOINT_TRUSTED_OWNERS)) return address()
return Resolved(PROCESS_CHECKPOINT_TRUSTED_OWNERS)
})
.map((owners) => ifElse(Array.isArray, always(owners), always([owners]))(owners))
.chain((owners) => {
return queryCheckpoints({
query: GET_AO_PROCESS_CHECKPOINTS,
variables: { owners, processId, limit: 50 },
processId,
before: LATEST
})
})
.map(path(['data', 'transactions', 'edges']))
.map(determineLatestCheckpoint)
.chain((latestCheckpoint) => {
Expand Down
48 changes: 39 additions & 9 deletions servers/cu/src/domain/client/ao-process.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,8 @@ describe('ao-process', () => {
loadTransactionData: async () => assert.fail('should not call if found in cache'),
logger,
PROCESS_IGNORE_ARWEAVE_CHECKPOINTS: [],
IGNORE_ARWEAVE_CHECKPOINTS: []
IGNORE_ARWEAVE_CHECKPOINTS: [],
PROCESS_CHECKPOINT_TRUSTED_OWNERS: []
}
const findLatestProcessMemory = findLatestProcessMemorySchema.implement(findLatestProcessMemoryWith(deps))

Expand Down Expand Up @@ -503,7 +504,8 @@ describe('ao-process', () => {
},
logger,
PROCESS_IGNORE_ARWEAVE_CHECKPOINTS: [],
IGNORE_ARWEAVE_CHECKPOINTS: []
IGNORE_ARWEAVE_CHECKPOINTS: [],
PROCESS_CHECKPOINT_TRUSTED_OWNERS: []
}
const findLatestProcessMemory = findLatestProcessMemorySchema.implement(findLatestProcessMemoryWith(deps))

Expand Down Expand Up @@ -596,7 +598,7 @@ describe('ao-process', () => {
queryGateway: async ({ query, variables }) => {
assert.ok(query)
assert.deepStrictEqual(variables, {
owner: 'address-123',
owners: ['address-123'],
processId: PROCESS,
limit: 50
})
Expand All @@ -610,7 +612,8 @@ describe('ao-process', () => {
},
logger,
PROCESS_IGNORE_ARWEAVE_CHECKPOINTS: [],
IGNORE_ARWEAVE_CHECKPOINTS: []
IGNORE_ARWEAVE_CHECKPOINTS: [],
PROCESS_CHECKPOINT_TRUSTED_OWNERS: []
}
const findLatestProcessMemory = findLatestProcessMemorySchema.implement(findLatestProcessMemoryWith(deps))

Expand Down Expand Up @@ -695,6 +698,29 @@ describe('ao-process', () => {
ordinate: cachedEval.ordinate
})
})

test('should query all trusted owners if not empty', async () => {
let assertionFailed = false
let addressCalled = false
const findLatestProcessMemory = findLatestProcessMemorySchema.implement(findLatestProcessMemoryWith({
...deps,
PROCESS_CHECKPOINT_TRUSTED_OWNERS: ['wallet-123', 'wallet-456'],
queryGateway: async ({ query, variables }) => {
try {
assert.deepStrictEqual(variables, { owners: ['wallet-123', 'wallet-456'], processId: 'process-123', limit: 50 })
assert.ok(query)
} catch (e) {
assertionFailed = true
}
return { data: { transactions: { edges: [] } } }
},
address: async () => { addressCalled = true }
}))
await findLatestProcessMemory(target)

assert.ok(!assertionFailed)
assert.ok(!addressCalled)
})
})

test('should decode if needed', async () => {
Expand Down Expand Up @@ -850,7 +876,7 @@ describe('ao-process', () => {
queryCheckpointGateway: async ({ query, variables }) => {
assert.ok(query)
assert.deepStrictEqual(variables, {
owner: 'address-123',
owners: ['address-123'],
processId: PROCESS,
limit: 50
})
Expand Down Expand Up @@ -904,7 +930,8 @@ describe('ao-process', () => {
},
logger,
PROCESS_IGNORE_ARWEAVE_CHECKPOINTS: [],
IGNORE_ARWEAVE_CHECKPOINTS: []
IGNORE_ARWEAVE_CHECKPOINTS: [],
PROCESS_CHECKPOINT_TRUSTED_OWNERS: []
}
const COLDSTART = {
src: 'cold_start',
Expand Down Expand Up @@ -977,7 +1004,8 @@ describe('ao-process', () => {
},
logger,
PROCESS_IGNORE_ARWEAVE_CHECKPOINTS: [],
IGNORE_ARWEAVE_CHECKPOINTS: []
IGNORE_ARWEAVE_CHECKPOINTS: [],
PROCESS_CHECKPOINT_TRUSTED_OWNERS: []
}

const findLatestProcessMemory = findLatestProcessMemorySchema.implement(findLatestProcessMemoryWith(deps))
Expand Down Expand Up @@ -1014,7 +1042,8 @@ describe('ao-process', () => {
},
logger,
PROCESS_IGNORE_ARWEAVE_CHECKPOINTS: [],
IGNORE_ARWEAVE_CHECKPOINTS: []
IGNORE_ARWEAVE_CHECKPOINTS: [],
PROCESS_CHECKPOINT_TRUSTED_OWNERS: []
}

const findLatestProcessMemory = findLatestProcessMemorySchema.implement(findLatestProcessMemoryWith(deps))
Expand Down Expand Up @@ -1063,7 +1092,8 @@ describe('ao-process', () => {
return new Response(Readable.toWeb(Readable.from(zipped)))
},
logger,
PROCESS_IGNORE_ARWEAVE_CHECKPOINTS: []
PROCESS_IGNORE_ARWEAVE_CHECKPOINTS: [],
PROCESS_CHECKPOINT_TRUSTED_OWNERS: []
}

const findLatestProcessMemory = findLatestProcessMemorySchema.implement(findLatestProcessMemoryWith(deps))
Expand Down
1 change: 1 addition & 0 deletions servers/cu/src/domain/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ export const createApis = async (ctx) => {
queryCheckpointGateway: ArweaveClient.queryGatewayWith({ fetch: ctx.fetch, GRAPHQL_URL: ctx.CHECKPOINT_GRAPHQL_URL, logger }),
PROCESS_IGNORE_ARWEAVE_CHECKPOINTS: ctx.PROCESS_IGNORE_ARWEAVE_CHECKPOINTS,
IGNORE_ARWEAVE_CHECKPOINTS: ctx.IGNORE_ARWEAVE_CHECKPOINTS,
PROCESS_CHECKPOINT_TRUSTED_OWNERS: ctx.PROCESS_CHECKPOINT_TRUSTED_OWNERS,
logger
}),
saveLatestProcessMemory: AoProcessClient.saveLatestProcessMemoryWith({
Expand Down
4 changes: 4 additions & 0 deletions servers/cu/src/domain/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ export const domainConfigSchema = z.object({
* on Arweave.
*/
PROCESS_IGNORE_ARWEAVE_CHECKPOINTS: commaDelimitedArraySchema,
/**
* An array of trusted owner wallets that Arweave checkpoints can be queried from.
*/
PROCESS_CHECKPOINT_TRUSTED_OWNERS: commaDelimitedArraySchema,
/**
* An array of checkpoint ids that should not be used
*/
Expand Down

0 comments on commit 3a8ef59

Please sign in to comment.