diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index e55942d..7bd9411 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -60,7 +60,7 @@ jobs: - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@0.21.0 with: - image-ref: ${{ steps.meta.outputs.tags }} + image-ref: ${{ env.IMAGE_NAME }}:latest format: 'table' exit-code: '1' ignore-unfixed: true diff --git a/db/migrations/1721920194282-Data.js b/db/migrations/1721920194282-Data.js new file mode 100644 index 0000000..41c7879 --- /dev/null +++ b/db/migrations/1721920194282-Data.js @@ -0,0 +1,17 @@ +module.exports = class Data1721920194282 { + name = 'Data1721920194282' + + async up(db) { + await db.query(`ALTER TABLE "send_packet" ADD "fee_deposited_id" character varying`) + await db.query(`ALTER TABLE "send_packet" ADD CONSTRAINT "UQ_0dcda86a7cfb4b2c7869d1ae9ae" UNIQUE ("fee_deposited_id")`) + await db.query(`CREATE UNIQUE INDEX "IDX_0dcda86a7cfb4b2c7869d1ae9a" ON "send_packet" ("fee_deposited_id") `) + await db.query(`ALTER TABLE "send_packet" ADD CONSTRAINT "FK_0dcda86a7cfb4b2c7869d1ae9ae" FOREIGN KEY ("fee_deposited_id") REFERENCES "send_packet_fee_deposited"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + } + + async down(db) { + await db.query(`ALTER TABLE "send_packet" DROP COLUMN "fee_deposited_id"`) + await db.query(`ALTER TABLE "send_packet" DROP CONSTRAINT "UQ_0dcda86a7cfb4b2c7869d1ae9ae"`) + await db.query(`DROP INDEX "public"."IDX_0dcda86a7cfb4b2c7869d1ae9a"`) + await db.query(`ALTER TABLE "send_packet" DROP CONSTRAINT "FK_0dcda86a7cfb4b2c7869d1ae9ae"`) + } +} diff --git a/db/migrations/1721920657518-Data.js b/db/migrations/1721920657518-Data.js new file mode 100644 index 0000000..9978ea5 --- /dev/null +++ b/db/migrations/1721920657518-Data.js @@ -0,0 +1,17 @@ +module.exports = class Data1721920657518 { + name = 'Data1721920657518' + + async up(db) { + await db.query(`CREATE INDEX "IDX_36524a30939bb522f1eda95267" ON "send_packet_fee_deposited" ("send_gas_limit") `) + await db.query(`CREATE INDEX "IDX_b05770c7b9f6fba9a0b12814e9" ON "send_packet_fee_deposited" ("send_gas_price") `) + await db.query(`CREATE INDEX "IDX_8847ac7451965338a765734545" ON "send_packet_fee_deposited" ("ack_gas_limit") `) + await db.query(`CREATE INDEX "IDX_bea86541f9bbed391be346275d" ON "send_packet_fee_deposited" ("ack_gas_price") `) + } + + async down(db) { + await db.query(`DROP INDEX "public"."IDX_36524a30939bb522f1eda95267"`) + await db.query(`DROP INDEX "public"."IDX_b05770c7b9f6fba9a0b12814e9"`) + await db.query(`DROP INDEX "public"."IDX_8847ac7451965338a765734545"`) + await db.query(`DROP INDEX "public"."IDX_bea86541f9bbed391be346275d"`) + } +} diff --git a/db/migrations/1721923283239-Data.js b/db/migrations/1721923283239-Data.js new file mode 100644 index 0000000..b3e73b8 --- /dev/null +++ b/db/migrations/1721923283239-Data.js @@ -0,0 +1,25 @@ +module.exports = class Data1721923283239 { + name = 'Data1721923283239' + + async up(db) { + await db.query(`ALTER TABLE "send_packet" DROP CONSTRAINT "FK_0dcda86a7cfb4b2c7869d1ae9ae"`) + await db.query(`DROP INDEX "public"."IDX_0dcda86a7cfb4b2c7869d1ae9a"`) + await db.query(`ALTER TABLE "send_packet" DROP CONSTRAINT "UQ_0dcda86a7cfb4b2c7869d1ae9ae"`) + await db.query(`ALTER TABLE "send_packet" DROP COLUMN "fee_deposited_id"`) + await db.query(`ALTER TABLE "send_packet_fee_deposited" ADD "send_packet_id" character varying`) + await db.query(`ALTER TABLE "send_packet_fee_deposited" ADD CONSTRAINT "UQ_9415c52ccc157e1a37c9f3f6235" UNIQUE ("send_packet_id")`) + await db.query(`CREATE UNIQUE INDEX "IDX_9415c52ccc157e1a37c9f3f623" ON "send_packet_fee_deposited" ("send_packet_id") `) + await db.query(`ALTER TABLE "send_packet_fee_deposited" ADD CONSTRAINT "FK_9415c52ccc157e1a37c9f3f6235" FOREIGN KEY ("send_packet_id") REFERENCES "send_packet"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + } + + async down(db) { + await db.query(`ALTER TABLE "send_packet" ADD CONSTRAINT "FK_0dcda86a7cfb4b2c7869d1ae9ae" FOREIGN KEY ("fee_deposited_id") REFERENCES "send_packet_fee_deposited"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`CREATE UNIQUE INDEX "IDX_0dcda86a7cfb4b2c7869d1ae9a" ON "send_packet" ("fee_deposited_id") `) + await db.query(`ALTER TABLE "send_packet" ADD CONSTRAINT "UQ_0dcda86a7cfb4b2c7869d1ae9ae" UNIQUE ("fee_deposited_id")`) + await db.query(`ALTER TABLE "send_packet" ADD "fee_deposited_id" character varying`) + await db.query(`ALTER TABLE "send_packet_fee_deposited" DROP COLUMN "send_packet_id"`) + await db.query(`ALTER TABLE "send_packet_fee_deposited" DROP CONSTRAINT "UQ_9415c52ccc157e1a37c9f3f6235"`) + await db.query(`DROP INDEX "public"."IDX_9415c52ccc157e1a37c9f3f623"`) + await db.query(`ALTER TABLE "send_packet_fee_deposited" DROP CONSTRAINT "FK_9415c52ccc157e1a37c9f3f6235"`) + } +} diff --git a/db/migrations/1721924207047-Data.js b/db/migrations/1721924207047-Data.js new file mode 100644 index 0000000..8adfb94 --- /dev/null +++ b/db/migrations/1721924207047-Data.js @@ -0,0 +1,11 @@ +module.exports = class Data1721924207047 { + name = 'Data1721924207047' + + async up(db) { + await db.query(`CREATE INDEX "IDX_f702d8ab77e40da621977ffe11" ON "send_packet" ("sequence") `) + } + + async down(db) { + await db.query(`DROP INDEX "public"."IDX_f702d8ab77e40da621977ffe11"`) + } +} diff --git a/db/migrations/1721926496341-Data.js b/db/migrations/1721926496341-Data.js new file mode 100644 index 0000000..56aa932 --- /dev/null +++ b/db/migrations/1721926496341-Data.js @@ -0,0 +1,19 @@ +module.exports = class Data1721926496341 { + name = 'Data1721926496341' + + async up(db) { + await db.query(`DROP INDEX "public"."IDX_9415c52ccc157e1a37c9f3f623"`) + await db.query(`ALTER TABLE "send_packet_fee_deposited" DROP CONSTRAINT "FK_9415c52ccc157e1a37c9f3f6235"`) + await db.query(`ALTER TABLE "send_packet_fee_deposited" DROP CONSTRAINT "UQ_9415c52ccc157e1a37c9f3f6235"`) + await db.query(`CREATE INDEX "IDX_9415c52ccc157e1a37c9f3f623" ON "send_packet_fee_deposited" ("send_packet_id") `) + await db.query(`ALTER TABLE "send_packet_fee_deposited" ADD CONSTRAINT "FK_9415c52ccc157e1a37c9f3f6235" FOREIGN KEY ("send_packet_id") REFERENCES "send_packet"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + } + + async down(db) { + await db.query(`CREATE UNIQUE INDEX "IDX_9415c52ccc157e1a37c9f3f623" ON "send_packet_fee_deposited" ("send_packet_id") `) + await db.query(`ALTER TABLE "send_packet_fee_deposited" ADD CONSTRAINT "FK_9415c52ccc157e1a37c9f3f6235" FOREIGN KEY ("send_packet_id") REFERENCES "send_packet"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + await db.query(`ALTER TABLE "send_packet_fee_deposited" ADD CONSTRAINT "UQ_9415c52ccc157e1a37c9f3f6235" UNIQUE ("send_packet_id")`) + await db.query(`DROP INDEX "public"."IDX_9415c52ccc157e1a37c9f3f623"`) + await db.query(`ALTER TABLE "send_packet_fee_deposited" DROP CONSTRAINT "FK_9415c52ccc157e1a37c9f3f6235"`) + } +} diff --git a/db/migrations/1721926766448-Data.js b/db/migrations/1721926766448-Data.js new file mode 100644 index 0000000..e4241d8 --- /dev/null +++ b/db/migrations/1721926766448-Data.js @@ -0,0 +1,15 @@ +module.exports = class Data1721926766448 { + name = 'Data1721926766448' + + async up(db) { + await db.query(`ALTER TABLE "open_channel_fee_deposited" ADD "open_channel_id" character varying`) + await db.query(`CREATE INDEX "IDX_a3c03e6c9e7053f39ef10aaab7" ON "open_channel_fee_deposited" ("open_channel_id") `) + await db.query(`ALTER TABLE "open_channel_fee_deposited" ADD CONSTRAINT "FK_a3c03e6c9e7053f39ef10aaab73" FOREIGN KEY ("open_channel_id") REFERENCES "channel_open_init"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`) + } + + async down(db) { + await db.query(`ALTER TABLE "open_channel_fee_deposited" DROP COLUMN "open_channel_id"`) + await db.query(`DROP INDEX "public"."IDX_a3c03e6c9e7053f39ef10aaab7"`) + await db.query(`ALTER TABLE "open_channel_fee_deposited" DROP CONSTRAINT "FK_a3c03e6c9e7053f39ef10aaab73"`) + } +} diff --git a/schema.graphql b/schema.graphql index 3c4391f..c830f1e 100644 --- a/schema.graphql +++ b/schema.graphql @@ -35,7 +35,7 @@ type SendPacket @entity { srcChannelId: String! @index sourceChannel: Channel packet: String! @index - sequence: BigInt! + sequence: BigInt! @index timeoutTimestamp: BigInt! blockNumber: BigInt! blockTimestamp: BigInt! @index @@ -52,6 +52,8 @@ type SendPacket @entity { polymerTxHash: String @index polymerGas: Int polymerBlockNumber: BigInt + + feesDeposited: [SendPacketFeeDeposited!] @derivedFrom(field: "sendPacket") } type RecvPacket @entity { @@ -228,6 +230,8 @@ type ChannelOpenInit @entity { polymerTxHash: String @index polymerGas: Int polymerBlockNumber: BigInt + + feesDeposited: [OpenChannelFeeDeposited!] @derivedFrom(field: "openChannel") } type ChannelOpenTry @entity { @@ -345,18 +349,19 @@ type ChannelCatchUpError @entity { } type SendPacketFeeDeposited @entity { - id: ID! - channelId: String! @index - sequence: BigInt! @index - sendGasLimit: BigInt! - sendGasPrice: BigInt! - ackGasLimit: BigInt! - ackGasPrice: BigInt! - blockNumber: BigInt! - blockTimestamp: BigInt! @index - transactionHash: String! @index - chainId: Int! @index - from: String! @index + id: ID! + channelId: String! @index + sequence: BigInt! @index + sendGasLimit: BigInt! @index + sendGasPrice: BigInt! @index + ackGasLimit: BigInt! @index + ackGasPrice: BigInt! @index + blockNumber: BigInt! + blockTimestamp: BigInt! @index + transactionHash: String! @index + chainId: Int! @index + from: String! @index + sendPacket: SendPacket @index } type OpenChannelFeeDeposited @entity { @@ -372,6 +377,7 @@ type OpenChannelFeeDeposited @entity { transactionHash: String! @index chainId: Int! @index from: String! @index + openChannel: ChannelOpenInit @index } type Transaction @entity { diff --git a/src/handlers/backfill.ts b/src/handlers/backfill.ts index 0edde6c..6d39ebf 100644 --- a/src/handlers/backfill.ts +++ b/src/handlers/backfill.ts @@ -1,6 +1,13 @@ import { Context } from "../utils/types"; import { BACKFILL_CONCURRENCY, CATCHUP_BATCH_SIZE, CATCHUP_ERROR_LIMIT, ENABLE_CATCHUP } from "../chains/constants"; -import { Channel, Packet, PacketCatchUpError } from "../model"; +import { + Channel, ChannelOpenInit, + OpenChannelFeeDeposited, + Packet, + PacketCatchUpError, + SendPacket, + SendPacketFeeDeposited +} from "../model"; import { And, IsNull, LessThan, MoreThan, Not } from "typeorm"; import { channelMetrics } from "./channels"; import { packetMetrics } from "./packets"; @@ -11,6 +18,9 @@ export async function handler(ctx: Context) { await updateMissingPacketMetrics(ctx); await updateMissingChannelMetrics(ctx); } + + await updateMissingSendPacketFees(ctx) + await updateMissingOpenChannelFeeDeposited(ctx) } export function getMissingChannelMetricsClauses() { @@ -131,3 +141,74 @@ async function updateMissingPacketMetrics(ctx: Context) { await packetMetrics(Array.from(uniquePacketIds), ctx, BACKFILL_CONCURRENCY); } + +async function updateMissingSendPacketFees(ctx: Context) { + let sendPacketFees = await ctx.store.find(SendPacketFeeDeposited, { + take: CATCHUP_BATCH_SIZE, + where: { + sendPacket: IsNull() + } + }) + + let updatedSendPackets: SendPacket[] = []; + let updatedSendPacketFees: SendPacketFeeDeposited[] = []; + + for (let sendPacketFee of sendPacketFees) { + let sendPacket = await ctx.store.findOne(SendPacket, + { + where: { + chainId: sendPacketFee.chainId, + srcChannelId: sendPacketFee.channelId, + sequence: sendPacketFee.sequence + } + }); + if (sendPacket) { + sendPacket.feesDeposited = [sendPacketFee]; + sendPacketFee.sendPacket = sendPacket; + + updatedSendPackets.push(sendPacket); + updatedSendPacketFees.push(sendPacketFee); + } else { + console.log(`Could not find send packet for send packet fee ${sendPacketFee.id}`); + } + } + + await ctx.store.upsert(updatedSendPackets); + await ctx.store.upsert(updatedSendPacketFees); +} + + +async function updateMissingOpenChannelFeeDeposited(ctx: Context) { + let openChannelFees = await ctx.store.find(OpenChannelFeeDeposited, { + take: CATCHUP_BATCH_SIZE, + where: { + openChannel: IsNull() + } + }) + + let updatedOpenChannels: ChannelOpenInit[] = []; + let updatedOpenChannelFees: OpenChannelFeeDeposited[] = []; + + for (let openChannelFee of openChannelFees) { + let openChannel = await ctx.store.findOne(ChannelOpenInit, + { + where: { + chainId: openChannelFee.chainId, + counterpartyPortId: openChannelFee.counterpartyPortId, + portAddress: openChannelFee.sourceAddress, + } + }); + if (openChannel) { + openChannel.feesDeposited = [openChannelFee]; + openChannelFee.openChannel = openChannel; + + updatedOpenChannels.push(openChannel); + updatedOpenChannelFees.push(openChannelFee); + } else { + console.log(`Could not find open channel for open channel fee ${openChannelFee.id}`); + } + } + + await ctx.store.upsert(updatedOpenChannels); + await ctx.store.upsert(updatedOpenChannelFees); +} \ No newline at end of file diff --git a/src/model/generated/channelOpenInit.model.ts b/src/model/generated/channelOpenInit.model.ts index 5ca27cc..e92f284 100644 --- a/src/model/generated/channelOpenInit.model.ts +++ b/src/model/generated/channelOpenInit.model.ts @@ -1,4 +1,5 @@ -import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, StringColumn as StringColumn_, IntColumn as IntColumn_, BooleanColumn as BooleanColumn_, BigIntColumn as BigIntColumn_, Index as Index_} from "@subsquid/typeorm-store" +import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, StringColumn as StringColumn_, IntColumn as IntColumn_, BooleanColumn as BooleanColumn_, BigIntColumn as BigIntColumn_, Index as Index_, OneToMany as OneToMany_} from "@subsquid/typeorm-store" +import {OpenChannelFeeDeposited} from "./openChannelFeeDeposited.model" @Entity_() export class ChannelOpenInit { @@ -84,4 +85,7 @@ export class ChannelOpenInit { @BigIntColumn_({nullable: true}) polymerBlockNumber!: bigint | undefined | null + + @OneToMany_(() => OpenChannelFeeDeposited, e => e.openChannel) + feesDeposited!: OpenChannelFeeDeposited[] } diff --git a/src/model/generated/openChannelFeeDeposited.model.ts b/src/model/generated/openChannelFeeDeposited.model.ts index 7ba7918..76e2107 100644 --- a/src/model/generated/openChannelFeeDeposited.model.ts +++ b/src/model/generated/openChannelFeeDeposited.model.ts @@ -1,4 +1,5 @@ -import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, StringColumn as StringColumn_, Index as Index_, IntColumn as IntColumn_, BigIntColumn as BigIntColumn_} from "@subsquid/typeorm-store" +import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, StringColumn as StringColumn_, Index as Index_, IntColumn as IntColumn_, BigIntColumn as BigIntColumn_, ManyToOne as ManyToOne_} from "@subsquid/typeorm-store" +import {ChannelOpenInit} from "./channelOpenInit.model" @Entity_() export class OpenChannelFeeDeposited { @@ -46,4 +47,8 @@ export class OpenChannelFeeDeposited { @Index_() @StringColumn_({nullable: false}) from!: string + + @Index_() + @ManyToOne_(() => ChannelOpenInit, {nullable: true}) + openChannel!: ChannelOpenInit | undefined | null } diff --git a/src/model/generated/sendPacket.model.ts b/src/model/generated/sendPacket.model.ts index 0b864a3..92733fb 100644 --- a/src/model/generated/sendPacket.model.ts +++ b/src/model/generated/sendPacket.model.ts @@ -1,6 +1,7 @@ -import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, StringColumn as StringColumn_, Index as Index_, ManyToOne as ManyToOne_, BigIntColumn as BigIntColumn_, IntColumn as IntColumn_, OneToOne as OneToOne_} from "@subsquid/typeorm-store" +import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, StringColumn as StringColumn_, Index as Index_, ManyToOne as ManyToOne_, BigIntColumn as BigIntColumn_, IntColumn as IntColumn_, OneToOne as OneToOne_, OneToMany as OneToMany_} from "@subsquid/typeorm-store" import {Channel} from "./channel.model" import {Packet} from "./packet.model" +import {SendPacketFeeDeposited} from "./sendPacketFeeDeposited.model" @Entity_() export class SendPacket { @@ -36,6 +37,7 @@ export class SendPacket { @StringColumn_({nullable: false}) packet!: string + @Index_() @BigIntColumn_({nullable: false}) sequence!: bigint @@ -92,4 +94,7 @@ export class SendPacket { @BigIntColumn_({nullable: true}) polymerBlockNumber!: bigint | undefined | null + + @OneToMany_(() => SendPacketFeeDeposited, e => e.sendPacket) + feesDeposited!: SendPacketFeeDeposited[] } diff --git a/src/model/generated/sendPacketFeeDeposited.model.ts b/src/model/generated/sendPacketFeeDeposited.model.ts index de21893..71d87c4 100644 --- a/src/model/generated/sendPacketFeeDeposited.model.ts +++ b/src/model/generated/sendPacketFeeDeposited.model.ts @@ -1,4 +1,5 @@ -import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, StringColumn as StringColumn_, Index as Index_, BigIntColumn as BigIntColumn_, IntColumn as IntColumn_} from "@subsquid/typeorm-store" +import {Entity as Entity_, Column as Column_, PrimaryColumn as PrimaryColumn_, StringColumn as StringColumn_, Index as Index_, BigIntColumn as BigIntColumn_, IntColumn as IntColumn_, ManyToOne as ManyToOne_} from "@subsquid/typeorm-store" +import {SendPacket} from "./sendPacket.model" @Entity_() export class SendPacketFeeDeposited { @@ -17,15 +18,19 @@ export class SendPacketFeeDeposited { @BigIntColumn_({nullable: false}) sequence!: bigint + @Index_() @BigIntColumn_({nullable: false}) sendGasLimit!: bigint + @Index_() @BigIntColumn_({nullable: false}) sendGasPrice!: bigint + @Index_() @BigIntColumn_({nullable: false}) ackGasLimit!: bigint + @Index_() @BigIntColumn_({nullable: false}) ackGasPrice!: bigint @@ -47,4 +52,8 @@ export class SendPacketFeeDeposited { @Index_() @StringColumn_({nullable: false}) from!: string + + @Index_() + @ManyToOne_(() => SendPacket, {nullable: true}) + sendPacket!: SendPacket | undefined | null }