-
Notifications
You must be signed in to change notification settings - Fork 2
Deploy randomness service #416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3482220
52ffad0
fff5813
6080a65
538867f
069a4c8
4891179
2535e5d
9c8d6b4
6b2bf13
52d7f07
29984b2
ebeb328
05fe002
161dd0c
6982226
eaaf485
3dde6bb
edad8d6
206d94a
4d2eba8
631afbe
f428bc5
32fad39
8afb643
2c7ba68
dc7f36a
3e61267
c4489a3
859ef94
b7dab0a
ac89a7d
70365db
1dec8f1
83c5c68
ea10681
dabb31d
7b83dfb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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 | ||
| 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 }} | ||
aodhgan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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 | ||
| 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, | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,7 +27,9 @@ class RandomnessService { | |
| rpc: { | ||
| url: env.RPC_URL, | ||
| allowDebug: true, | ||
| pollingInterval: 250, | ||
| }, | ||
| maxPriorityFeePerGas: 10n, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I created this issue to implement this: https://linear.app/happychain/issue/HAPPY-372/estimate-maxpriorityfeepergas |
||
| }) | ||
| this.transactionFactory = new TransactionFactory(this.txm, env.RANDOM_CONTRACT_ADDRESS, env.PRECOMMIT_DELAY) | ||
| this.drandService = new DrandService(this.drandRepository, this.transactionFactory) | ||
|
|
||
| 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"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,6 +41,7 @@ export class NonceManager { | |
|
|
||
| const blockchainNonce = await this.txmgr.viemClient.getTransactionCount({ | ||
| address: address, | ||
| blockTag: "pending", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why this change? obviously defaults to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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() | ||
|
|
||
| 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 } |
| 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 = { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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, | ||
| } | ||
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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 abovescript?