Skip to content

Commit

Permalink
Add keychain bridge
Browse files Browse the repository at this point in the history
  • Loading branch information
shanejearley committed Jul 24, 2023
1 parent 99c5f7b commit c9dbc81
Show file tree
Hide file tree
Showing 17 changed files with 913 additions and 861 deletions.
2 changes: 0 additions & 2 deletions common/data/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import walletSchema from './schemas/wallet.schema.json'
import stakingActionSchema from './schemas/staking_action.schema.json'
import userAccountSchema from './schemas/user_account.schema.json'
import operatorStore from './mock/operator.store.json'
import validatorStore from './mock/validator.store.json'
import accountStore from './mock/account.store.json'
import userStore from './mock/user.store.json'
import { Postgres } from '../../../services/users/src/providers/postgres'
Expand All @@ -24,7 +23,6 @@ export {
accountStore,
userStore,
operatorStore,
validatorStore,
Postgres,
Schema
}
Expand Down
158 changes: 0 additions & 158 deletions common/data/src/mock/validator.store.json

This file was deleted.

1,239 changes: 698 additions & 541 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions services/oracle/scripts/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,24 @@ void async function () {
process.env.SSV_TOKEN_ADDRESS = '0x3a9f01091C446bdE031E39ea8354647AFef091E7'
process.env.UNISWAP_V3_FACTORY_ADDRESS = '0x1F98431c8aD98523631AE4a59f267346ea31F984'
process.env.WETH_TOKEN_ADDRESS = '0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6'
process.env.STRATEGY = 'dkg'
process.env.CLI_PATH = `./${resourcePath}/rockx-dkg-cli/build/bin/rockx-dkg-cli`
process.env.MESSENGER_SRV_ADDR = 'http://0.0.0.0:3000'
process.env.USE_HARDCODED_OPERATORS = 'true'

await run(`make -C ${resourcePath}/rockx-dkg-cli build`)
const cli = await run(`which ${process.env.CLI_PATH}`)
if (!cli) throw new Error('DKG CLI not found')

if (!cli) throw new Error('Dkg cli not found')
if (os.platform() === 'linux') {
await run(`docker compose -f ${resourcePath}/rockx-dkg-cli/docker-compose.yaml -f ${resourcePath}/../docker-compose.override.yaml up -d`)
} else {
await run(`docker compose -f ${resourcePath}/rockx-dkg-cli/docker-compose.yaml up -d`)
}
console.log('🔑 DKG service started')

const ping = await fetchRetry(`${process.env.MESSENGER_SRV_ADDR}/ping`)
const { message } = await ping.json()
if (message !== 'pong') throw new Error('DKG service is not running')
if (message !== 'pong') throw new Error('Dkg service is not running')
console.log('🔑 Dkg service started')

run('npx esno -r dotenv/config src/index.ts')
console.log('🔑 Oracle service started')
}()
16 changes: 7 additions & 9 deletions services/oracle/scripts/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import os from 'os'
import fs from 'fs'
import { ethers } from 'ethers'
import { fetchRetry, run } from '@casimir/helpers'
import { DKG } from '@casimir/oracle/src/providers/dkg'
import { Dkg } from '@casimir/oracle/src/providers/dkg'
import { Validator } from '@casimir/types'

void async function () {
Expand Down Expand Up @@ -39,21 +39,18 @@ void async function () {
const validators = JSON.parse(fs.readFileSync(`${outputPath}/validators.json`, 'utf8') || '{}')

if (!validators[oracleAddress] || Object.keys(validators[oracleAddress]).length < validatorCount) {

await run(`make -C ${resourcePath}/rockx-dkg-cli build`)
const cli = await run(`which ${process.env.CLI_PATH}`)
if (!cli) throw new Error('DKG CLI not found')

if (!cli) throw new Error('Dkg cli not found')
if (os.platform() === 'linux') {
await run(`docker compose -f ${resourcePath}/rockx-dkg-cli/docker-compose.yaml -f ${resourcePath}/../docker-compose.override.yaml up -d`)
} else {
await run(`docker compose -f ${resourcePath}/rockx-dkg-cli/docker-compose.yaml up -d`)
}
console.log('🔑 DKG service started')

}
const ping = await fetchRetry(`${process.env.MESSENGER_SRV_ADDR}/ping`)
const { message } = await ping.json()
if (message !== 'pong') throw new Error('DKG service is not running')
if (message !== 'pong') throw new Error('Dkg service is not running')
console.log('🔑 Dkg service started')

let nonce = 3

Expand All @@ -67,9 +64,10 @@ void async function () {
})

const newOperatorIds = [1, 2, 3, 4] // Todo get new group here
const dkg = new DKG({ cliPath: process.env.CLI_PATH, messengerUrl: process.env.MESSENGER_SRV_ADDR })
const dkg = new Dkg({ cliPath: process.env.CLI_PATH, messengerUrl: process.env.MESSENGER_SRV_ADDR })

const validator = await dkg.createValidator({
poolId: i + 1,
operatorIds: newOperatorIds,
withdrawalAddress: poolAddress
})
Expand Down
32 changes: 24 additions & 8 deletions services/oracle/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
console.log('STARTING')
import { ethers } from 'ethers'
console.log('ETHERS', JSON.stringify(ethers, null, 4))
import { getConfig } from './providers/config'
console.log('GETCONFIG', JSON.stringify(getConfig, null, 4))
import { getEventsIterable } from './providers/events'
import {
initiateDepositHandler,
console.log('GETEVENTSITERABLE', JSON.stringify(getEventsIterable, null, 4))
import {
initiateDepositHandler,
// initiateResharesHandler,
// initiateExitsHandler,
// reportForcedExitsHandler,
reportCompletedExitsHandler
} from './providers/handlers'
console.log('INITIATEDEPOSITHANDLER', JSON.stringify(initiateDepositHandler, null, 4))
console.log('REPORTCOMPLETEDEXITSHANDLER', JSON.stringify(reportCompletedExitsHandler, null, 4))

void async function () {

const { manager } = getConfig()
const config = getConfig()
console.log('CONFIG', JSON.stringify(config, null, 4))

void async function () {
const handlers = {
DepositRequested: initiateDepositHandler,
/**
Expand All @@ -22,15 +29,24 @@ void async function () {
*/
CompletedExitReportsRequested: reportCompletedExitsHandler
}

const eventsIterable = getEventsIterable({ manager, events: Object.keys(handlers) })
console.log('HANDLERS', JSON.stringify(handlers, null, 4))
const provider = new ethers.providers.JsonRpcProvider(config.ethereumUrl)
console.log('PROVIDER', JSON.stringify(provider, null, 4))

const eventsIterable = getEventsIterable({
ethereumUrl: config.ethereumUrl,
manager: config.manager,
events: Object.keys(handlers)
})

for await (const event of eventsIterable) {
console.log('EVENT', JSON.stringify(event, null, 4))
const details = event?.[event.length - 1]
const { args } = details
console.log(`Handling ${details.event} with args ${JSON.stringify(args)}`)
const handler = handlers[details.event as keyof typeof handlers]
if (!handler) throw new Error(`No handler found for event ${details.event}`)
await handler(args)
await handler({ args, strategy: config.strategy })
}
}()

Expand Down
2 changes: 0 additions & 2 deletions services/oracle/src/interfaces/DKGOptions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
export interface DkgOptions {
/** DKG CLI path */
cliPath: string
/** DKG messenger service URL */
messengerUrl: string
}
8 changes: 7 additions & 1 deletion services/oracle/src/interfaces/HandlerInput.ts
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
export type HandlerInput = Record<string | number, string | number | boolean>
export interface HandlerInput {
args: {
poolId?: number
count?: number
}
strategy: string
}
5 changes: 5 additions & 0 deletions services/oracle/src/interfaces/KeychainOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface KeychainOptions {
strategy: string
cliPath: string
messengerUrl?: string
}
4 changes: 0 additions & 4 deletions services/oracle/src/interfaces/ReshareValidatorInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ import { CasimirManager } from '@casimir/ethereum/build/artifacts/types'
import { ethers } from 'ethers'

export interface ReshareValidatorInput {
/** JSON RPC provider */
provider: ethers.providers.JsonRpcProvider
/** Manager contract */
manager: ethers.Contract & CasimirManager
/** Validator public key */
publicKey: string
/** Pool ID */
Expand Down
17 changes: 10 additions & 7 deletions services/oracle/src/providers/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,25 @@ import CasimirManagerJson from '@casimir/ethereum/build/artifacts/src/v1/Casimir
import CasimirViewsJson from '@casimir/ethereum/build/artifacts/src/v1/CasimirViews.sol/CasimirViews.json'
import { CasimirManager, CasimirViews } from '@casimir/ethereum/build/artifacts/types'

const supportedStrategies = ['dkg', 'ethdo']

export function getConfig() {
const ethereumUrl = process.env.ETHEREUM_RPC_URL
if (!ethereumUrl) throw new Error('No ethereum rpc url provided')
const provider = new ethers.providers.JsonRpcProvider(ethereumUrl)

const mnemonic = process.env.BIP39_SEED
if (!mnemonic) throw new Error('No mnemonic provided')
const pathIndex = process.env.BIP39_PATH_INDEX
const path = `m/44'/60'/0'/0/${pathIndex || 0}`
const signer = ethers.Wallet.fromMnemonic(mnemonic, path).connect(provider)
const wallet = ethers.Wallet.fromMnemonic(mnemonic, path)

const managerAddress = process.env.MANAGER_ADDRESS
if (!managerAddress) throw new Error('No manager address provided')
const manager = new ethers.Contract(managerAddress, CasimirManagerJson.abi, provider) as ethers.Contract & CasimirManager
const manager = new ethers.Contract(managerAddress, CasimirManagerJson.abi) as ethers.Contract & CasimirManager

const viewsAddress = process.env.VIEWS_ADDRESS
if (!viewsAddress) throw new Error('No views address provided')
const views = new ethers.Contract(viewsAddress, CasimirViewsJson.abi, provider) as CasimirViews & ethers.Contract
const views = new ethers.Contract(viewsAddress, CasimirViewsJson.abi) as CasimirViews & ethers.Contract

const linkTokenAddress = process.env.LINK_TOKEN_ADDRESS
if (!linkTokenAddress) throw new Error('No link token address provided')
Expand All @@ -35,15 +36,16 @@ export function getConfig() {
const wethTokenAddress = process.env.WETH_TOKEN_ADDRESS
if (!wethTokenAddress) throw new Error('No weth token address provided')

const strategy = process.env.STRATEGY
if (!strategy || !supportedStrategies.includes(strategy)) throw new Error('No strategy provided')
const cliPath = process.env.CLI_PATH
if (!cliPath) throw new Error('No cli path provided')
const messengerUrl = process.env.MESSENGER_SRV_ADDR
if (!messengerUrl) throw new Error('No messenger url provided')
if (!messengerUrl && strategy === 'dkg') throw new Error('No messenger url provided')

return {
ethereumUrl,
provider,
signer,
wallet,
manager,
views,
linkTokenAddress,
Expand All @@ -52,6 +54,7 @@ export function getConfig() {
ssvTokenAddress,
uniswapV3FactoryAddress,
wethTokenAddress,
strategy,
cliPath,
messengerUrl
}
Expand Down
21 changes: 4 additions & 17 deletions services/oracle/src/providers/dkg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { getWithdrawalCredentials, run, runRetry } from '@casimir/helpers'
import { CreateValidatorInput } from '../interfaces/CreateValidatorInput'
import { Validator } from '@casimir/types'
import { ReshareValidatorInput } from '../interfaces/ReshareValidatorInput'
import { operatorStore } from '@casimir/data'
import { getOperatorUrls } from './registry'
import { DepositDataInput } from '../interfaces/DepositDataInput'

export class Dkg {
Expand All @@ -27,7 +27,7 @@ export class Dkg {
async createValidator(input: CreateValidatorInput, retriesLeft: number | undefined = 25): Promise<Validator> {
try {
const { poolId, operatorIds, withdrawalAddress } = input
const operators = this.getOperatorUrls(operatorIds)
const operators = getOperatorUrls(operatorIds)
const ceremonyId = await this.startKeygen({ operators, withdrawalAddress })

console.log(`Started ceremony ${ceremonyId} for pool ${poolId}`)
Expand Down Expand Up @@ -61,8 +61,8 @@ export class Dkg {
async reshareValidator(input: ReshareValidatorInput, retriesLeft: number | undefined = 25): Promise<Validator> {
try {
const { poolId, operatorIds, publicKey, oldOperatorIds, withdrawalAddress } = input
const operators = this.getOperatorUrls(operatorIds)
const oldOperators = this.getOperatorUrls(oldOperatorIds)
const operators = getOperatorUrls(operatorIds)
const oldOperators = getOperatorUrls(oldOperatorIds)
const ceremonyId = await this.startReshare({ operators, publicKey, oldOperators })

console.log(`Started ceremony ${ceremonyId} for pool ${poolId}`)
Expand Down Expand Up @@ -163,17 +163,4 @@ export class Dkg {
withdrawalCredentials: `0x${withdrawalCredentials}`
}
}

/**
* Get operator URLs
* @param {number[]} operatorIds - Operator IDs
* @returns {<Record<string, string>} Operator group
*/
getOperatorUrls(operatorIds: number[]): Record<string, string> {
return operatorIds.reduce((group: Record<string, string>, id: number) => {
const key = id.toString() as keyof typeof operatorStore
group[key] = operatorStore[key]
return group
}, {})
}
}
7 changes: 6 additions & 1 deletion services/oracle/src/providers/ethdo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@ import { CreateValidatorInput } from '../interfaces/CreateValidatorInput'
import { Validator } from '@casimir/types'

export class Ethdo {

cliPath: string

constructor(options: { cliPath: string }) {
this.cliPath = options.cliPath
}
// async createValidator(input: CreateValidatorInput, retriesLeft: number | undefined = 25): Promise<Validator> {},
// async reshareValidator(input: ReshareValidatorInput, retriesLeft: number | undefined = 25): Promise<Validator> {},
// async getDepositData(input: DepositDataInput, retriesLeft: number | undefined = 25): Promise<DepositData> {},
// async getShares(ceremonyId: string, retriesLeft: number | undefined = 25): Promise<Shares> {},
// async startKeygen(input: StartKeygenInput, retriesLeft: number | undefined = 25): Promise<string> {},
// async getOperatorUrls(operatorIds: number[], retriesLeft: number | undefined = 25): Promise<string[]> {},
}
6 changes: 5 additions & 1 deletion services/oracle/src/providers/events.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { ethers } from 'ethers'

export function getEventsIterable({ manager, events }: { manager: ethers.Contract, events: string[] }) {
export function getEventsIterable({ manager, events }: {
ethereumUrl: string,
manager: ethers.Contract,
events: string[]
}) {
return (async function*() {
for (const event of events) {
yield* getEvent({ manager, event })
Expand Down
Loading

0 comments on commit c9dbc81

Please sign in to comment.