Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
3482220
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
52ffad0
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
fff5813
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
6080a65
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
538867f
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
069a4c8
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
4891179
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
2535e5d
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
9c8d6b4
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
6b2bf13
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
52d7f07
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
29984b2
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
ebeb328
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
05fe002
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
161dd0c
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
6982226
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
eaaf485
chore: deploy randomness
GabrielMartinezRodriguez Feb 5, 2025
3dde6bb
chore: deploy randomness
GabrielMartinezRodriguez Feb 6, 2025
edad8d6
chore: deploy randomness
GabrielMartinezRodriguez Feb 6, 2025
206d94a
chore: deploy randomness
GabrielMartinezRodriguez Feb 6, 2025
4d2eba8
chore: deploy randomness
GabrielMartinezRodriguez Feb 6, 2025
631afbe
fix(randomness): increased gas limit and tip
GabrielMartinezRodriguez Feb 6, 2025
f428bc5
chore(randomness): increased polling interval
GabrielMartinezRodriguez Feb 6, 2025
32fad39
chore(randomness): added console.log for monitor txm stuck
GabrielMartinezRodriguez Feb 7, 2025
8afb643
chore(randomness): changed monitoring logs
GabrielMartinezRodriguez Feb 7, 2025
2c7ba68
chore(randomness): changed monitoring logs
GabrielMartinezRodriguez Feb 7, 2025
dc7f36a
chore(randomness): changed monitoring logs
GabrielMartinezRodriguez Feb 7, 2025
3e61267
chore(txm): remove console log
GabrielMartinezRodriguez Feb 11, 2025
c4489a3
chore(randomness): change identation
GabrielMartinezRodriguez Feb 11, 2025
859ef94
chore(txm): new block received
GabrielMartinezRodriguez Feb 12, 2025
b7dab0a
chore(txm): added debug log
GabrielMartinezRodriguez Feb 12, 2025
ac89a7d
chore(txm): change identation again
GabrielMartinezRodriguez Feb 12, 2025
70365db
chore(randomness): added comment
GabrielMartinezRodriguez Feb 12, 2025
1dec8f1
chore(randomness): removed console.log and not deploy on pr
GabrielMartinezRodriguez Feb 12, 2025
83c5c68
chore(randomness): removed comment
GabrielMartinezRodriguez Feb 12, 2025
ea10681
chore(randomness): remove console.log
GabrielMartinezRodriguez Feb 14, 2025
dabb31d
chore(randomness): pr review
GabrielMartinezRodriguez Feb 17, 2025
7b83dfb
chore: format
GabrielMartinezRodriguez Feb 17, 2025
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
91 changes: 91 additions & 0 deletions .github/workflows/deploy-randomness.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Deploy Randomness

on:
workflow_dispatch:

env:
REGISTRY: ghcr.io
ORGANIZATION: happychaindevs
PM2_PROCESS_NAME: randomness
RANDOMNESS_DB_PATH: /home/randomness/randomness.sqlite
TXM_DB_PATH: /home/randomness/txm.sqlite


jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout code
uses: actions/checkout@v4.2.0

- uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Build code
run: |
make randomness.build

- name: Copy files to server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
key: ${{ secrets.SERVER_KEY }}
port: ${{ secrets.SERVER_PORT }}
source: "apps/randomness/build/*,node_modules/better-sqlite3,node_modules/bindings,node_modules/file-uri-to-path"
target: /home/deployer/randomness
strip_components: 1
rm: true

- name: Deploy randomness to server
uses: appleboy/ssh-action@v1.1.0
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
key: ${{ secrets.SERVER_KEY }}
port: ${{ secrets.SERVER_PORT }}
# We copy better-sqlite3, bindings, and file-uri-to-path separately because the bundled file does not include
# better-sqlite3 and its dependencies
script: |
chmod -R o+rX /home/deployer/randomness
mv /home/deployer/randomness /tmp
sudo -u randomness bash -c '
rm -rf /home/randomness/build
rm -rf /home/randomness/node_modules
cp -r /tmp/randomness/randomness/build /home/randomness/build

mkdir -p /home/randomness/node_modules
cp -r /tmp/randomness/better-sqlite3 /home/randomness/node_modules/better-sqlite3
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add a comment about why we need to copy these files separately?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to put a comment there, but as you can see, the problem is that this part of the code is a script that we execute on behalf of the user randomness:
sudo -u randomness bash -c 'script'
The problem is that if you add comments there, the script fails. Where would you add that comment if not here? Maybe at the top of the file?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could it work just above sudo? Or just above script?

cp -r /tmp/randomness/bindings /home/randomness/node_modules/bindings
cp -r /tmp/randomness/file-uri-to-path /home/randomness/node_modules/file-uri-to-path

cd /home/randomness

rm -f .env

cat > .env <<-EOF
export PRIVATE_KEY=${{ secrets.RANDOMNESS_PRIVATE_KEY }}
export TXM_DB_PATH=${{ env.TXM_DB_PATH }}
export RANDOMNESS_DB_PATH=${{ env.RANDOMNESS_DB_PATH }}
export ${{vars.RANDOMNESS_ENV}}
EOF

npm rebuild

pm2 delete ${{ env.PM2_PROCESS_NAME }}

source .env && node ./build/migrate.es.js

source .env && pm2 start ./build/index.es.js \
--name ${{ env.PM2_PROCESS_NAME }}
pm2 save
'
rm -rf /tmp/randomness
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,11 @@ contracts.build:
cd contracts && make build
.PHONY: contracts.build

randomness.build: setup.ts shared.build
cd packages/txm && make build
cd apps/randomness && make build
.PHONY: randomness.build

# ==================================================================================================
# DOCS

Expand Down
4 changes: 2 additions & 2 deletions apps/randomness/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ start: ## Starts the randomness service
.PHONY: start

migrate: ## Runs pending migrations
tsx --env-file=.env src/migrate.ts
.PHONY: migrate
node --env-file=.env dist/migrate.es.js
PHONY: migrate

link-anvil:
rm src/ABI/random.ts
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Kysely } from "kysely"
import type { Database } from "../src/db/types"
import type { Database } from "../types"

export async function up(db: Kysely<Database>) {
await db.schema
Expand All @@ -12,3 +12,5 @@ export async function up(db: Kysely<Database>) {
.addColumn("status", "text", (col) => col.notNull())
.execute()
}

export const migration20241210123000 = { up }
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Kysely } from "kysely"
import type { Database } from "../src/db/types"
import type { Database } from "../types"

export async function up(db: Kysely<Database>) {
await db.schema
Expand All @@ -10,3 +10,5 @@ export async function up(db: Kysely<Database>) {
.addColumn("transactionIntentId", "text")
.execute()
}

export const migration20241219104500 = { up }
7 changes: 7 additions & 0 deletions apps/randomness/src/db/migrations/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { migration20241210123000 } from "./Migration20241210123000"
import { migration20241219104500 } from "./Migration20241219104500"

export const migrations = {
"20241210123000": migration20241210123000,
"20241219104500": migration20241219104500,
}
2 changes: 2 additions & 0 deletions apps/randomness/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ class RandomnessService {
rpc: {
url: env.RPC_URL,
allowDebug: true,
pollingInterval: 250,
},
maxPriorityFeePerGas: 10n,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setting this - i believe we dont do any gas estimation rpc calls, or do we still do the call for baseFee? - which would return a maxPriorityFeePerGas field anyway, so would it not be more effective to set a value calculated from this? i expect hardcoding this to 10 Gwei will be effective in most cases, but under extreme network congestion this might be exceeded

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think you are right. I believe we should implement a mechanism to predict the recommended tip. It's true that the tip on the network is currently 0, and we need to add at least 1, because if we don't offer a tip, the problem is that the sequencer will not accept the new block that includes our transaction if our transaction arrives late to the blockchain. More context: https://docs.optimism.io/operators/node-operators/configuration/execution-config#minerrecommit

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

})
this.transactionFactory = new TransactionFactory(this.txm, env.RANDOM_CONTRACT_ADDRESS, env.PRECOMMIT_DELAY)
this.drandService = new DrandService(this.drandRepository, this.transactionFactory)
Expand Down
21 changes: 11 additions & 10 deletions apps/randomness/src/migrate.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { promises as fs } from "node:fs"
import path from "node:path"
import { fileURLToPath } from "node:url"
import { FileMigrationProvider, Migrator } from "kysely"
import { type Migration, type MigrationProvider, Migrator } from "kysely"
import { db } from "./db/driver"
import { migrations } from "./db/migrations"
import "@happy.tech/txm/migrate"

const dirname = path.dirname(fileURLToPath(import.meta.url))
class ObjectMigrationProvider implements MigrationProvider {
constructor(private migrations: Record<string, Migration>) {}

async getMigrations(): Promise<Record<string, Migration>> {
return this.migrations
}
}

async function migrateToLatest() {
const migrator = new Migrator({
db,
provider: new FileMigrationProvider({
fs,
path,
migrationFolder: path.join(dirname, "../migrations"),
}),
provider: new ObjectMigrationProvider(migrations),
})

const { error, results } = await migrator.migrateToLatest()
Expand Down
2 changes: 1 addition & 1 deletion apps/randomness/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"extends": ["../../support/configs/tsconfig.base.json"],
"include": ["*.ts", "src", "migrations"]
"include": ["*.ts", "src"]
}
1 change: 1 addition & 0 deletions packages/txm/build.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { defineConfig } from "@happy.tech/happybuild"

export default defineConfig({
exports: [".", "./migrate"],
bunConfig: {
minify: false,
target: "node",
Expand Down
1 change: 1 addition & 0 deletions packages/txm/lib/NonceManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export class NonceManager {

const blockchainNonce = await this.txmgr.viemClient.getTransactionCount({
address: address,
blockTag: "pending",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this change? obviously defaults to latest, wondering if this has other ramifications to the txm design

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because with "pending," we obtain transactions that are also in the mempool, so the initial nonce will be more accurate

})

const highestDbNonce = this.txmgr.transactionRepository.getHighestNonce()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Kysely } from "kysely"
import type { Database } from "../lib/db/types"
import type { Database } from "../types"

export async function up(db: Kysely<Database>) {
async function up(db: Kysely<Database>) {
await db.schema
.createTable("transaction")
.addColumn("intentId", "text", (col) => col.notNull())
Expand All @@ -16,3 +16,5 @@ export async function up(db: Kysely<Database>) {
.addColumn("metadata", "json")
.execute()
}

export const migration20241111163800 = { up }
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import type { Kysely } from "kysely"
import type { Database } from "../lib/db/types"
import type { Database } from "../types"

/*
SQLite does not have native time types. The SQL interface allows arbitrary type names including "DATE" and "DATETIME",
but this is invalid in this API, and results in "NUMERIC" affinity instead of "INTEGER" affinity,
which is the one we want here
*/
export async function up(db: Kysely<Database>) {
async function up(db: Kysely<Database>) {
await db.schema.alterTable("transaction").addColumn("createdAt", "integer").execute()

await db.schema.alterTable("transaction").addColumn("updatedAt", "integer").execute()
}

export const migration20241111223000 = { up }
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { Kysely } from "kysely"
import type { Database } from "../lib/db/types"
import type { Database } from "../types"

export async function up(db: Kysely<Database>) {
async function up(db: Kysely<Database>) {
await db.schema
.alterTable("transaction")
.addColumn("from", "text", (col) => col.notNull())
.execute()
}

export const migration20241205104400 = { up }
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { Kysely } from "kysely"
import type { Database } from "../lib/db/types"
import type { Database } from "../types"

export async function up(db: Kysely<Database>) {
await db.schema.alterTable("transaction").addColumn("collectionBlock", "integer").execute()
}

export const migration20250121110600 = { up }
11 changes: 11 additions & 0 deletions packages/txm/lib/db/migrations/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { migration20241111163800 } from "./Migration20241111163800"
import { migration20241111223000 } from "./Migration20241111223000"
import { migration20241205104400 } from "./Migration20241205104400"
import { migration20250121110600 } from "./Migration20250121110600"

export const migrations = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forgive my memory (I know you mentioned at standup one morning) but why are we moving to object based migrations? is it simply to make the workflow process easier? what are the tradeoffs

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did it this way because we need to include the migrations in the bundle file. If we don't import the files, the Happy Build won't include them in the index.es.js that we are deploying, and deploying the migration would be much more tedious

"20241111163800": migration20241111163800,
"20241111223000": migration20241111223000,
"20241205104400": migration20241205104400,
"20250121110600": migration20250121110600,
}
22 changes: 11 additions & 11 deletions packages/txm/lib/migrate.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { promises as fs } from "node:fs"
import path from "node:path"
import { fileURLToPath } from "node:url"
import { FileMigrationProvider, Migrator } from "kysely"
import { type Migration, type MigrationProvider, Migrator } from "kysely"
import { db } from "./db/driver"
import { migrations } from "./db/migrations"

const dirname = path.dirname(fileURLToPath(import.meta.url))
class ObjectMigrationProvider implements MigrationProvider {
constructor(private migrations: Record<string, Migration>) {}

async function migrateToLatest() {
async getMigrations(): Promise<Record<string, Migration>> {
return this.migrations
}
}

export async function migrateToLatest() {
const migrator = new Migrator({
db,
provider: new FileMigrationProvider({
fs,
path,
migrationFolder: path.join(dirname, "../migrations"),
}),
provider: new ObjectMigrationProvider(migrations),
})

const { error, results } = await migrator.migrateToLatest()
Expand Down
4 changes: 4 additions & 0 deletions packages/txm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
".": {
"default": "./dist/index.es.js",
"types": "./dist/index.es.d.ts"
},
"./migrate": {
"default": "./dist/migrate.es.js",
"types": "./dist/migrate.es.d.ts"
}
},
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/txm/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@
"ts-node": ["./node_modules/ts-node/dist/bin.js"]
}
},
"include": ["lib", "*.ts", "package.json", "migrations"]
"include": ["lib", "*.ts", "package.json"]
}
Loading