Skip to content

Commit

Permalink
Added A seperate migration for traceability
Browse files Browse the repository at this point in the history
  • Loading branch information
aruokhai committed Jan 8, 2025
1 parent 816037f commit e5854bd
Show file tree
Hide file tree
Showing 14 changed files with 134 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{
"type": "node",
"request": "launch",
"name": "Launch via NPM",
"name": "Debug e2e Test",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run",
Expand Down
60 changes: 59 additions & 1 deletion e2e/indexer.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { UTXO, WalletHelper, AddressType } from '@e2e/helpers/wallet.helper';
import { transactionToEntity } from '@e2e/helpers/common.helper';
import { btcToSats, transactionToEntity } from '@e2e/helpers/common.helper';
import { initialiseDep } from '@e2e/setup';
import { ApiHelper } from '@e2e/helpers/api.helper';
import { SilentBlocksService } from '@/silent-blocks/silent-blocks.service';
Expand Down Expand Up @@ -74,4 +74,62 @@ describe('Indexer', () => {
expect(response.data).toEqual(silentBlock);
},
);

it('Should exclude spent transactions when the "FilterSpent" flag is set to true', async () => {
const taprootOutput = walletHelper.generateAddresses(
1,
AddressType.P2TR,
)[0];
const outputs = walletHelper.generateAddresses(6, AddressType.P2WPKH);
const utxos: UTXO[] = [];

for (const [index, output] of outputs.entries()) {
const utxo = await walletHelper.addFundToUTXO(
output,
1,
AddressType.P2WPKH,
index,
);
utxos.push(utxo);
}

const { transaction, txid, blockHash } =
await walletHelper.craftAndSendTransaction(
utxos,
taprootOutput,
5.999,
0.001,
);

const utxo: UTXO = {
rawTx: transaction.toHex(),
txid,
vout: 0,
value: btcToSats(5.999),
addressType: AddressType.P2TR,
index: 0,
};

await walletHelper.craftAndSendTransaction(
[utxo],
taprootOutput,
5.998,
0.001,
);

await new Promise((resolve) => setTimeout(resolve, 30000));
const response = await apiHelper.get(
`/silent-block/hash/${blockHash}?filterSpent=true`,
{
responseType: 'arraybuffer',
},
);

const silentBlock = new SilentBlocksService(
{} as any,
{} as any,
).encodeSilentBlock([]);

expect(response.data).toEqual(silentBlock);
});
});
37 changes: 37 additions & 0 deletions migrations/1736332353003-migrations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { MigrationInterface, QueryRunner } from 'typeorm';

export class Migrations1736332353003 implements MigrationInterface {
name = 'MIgrations1736332353003';

public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
CREATE TABLE "transaction_output" (
"id" integer PRIMARY KEY NOT NULL,
"pubKey" text NOT NULL,
"vout" integer NOT NULL,
"value" integer NOT NULL,
"isSpent" boolean NOT NULL DEFAULT false,
"transactionId" INTEGER NOT NULL,
CONSTRAINT "FK_transaction_transaction_output" FOREIGN KEY ("transactionId") REFERENCES "transaction"("id") ON DELETE CASCADE
)
`);
await queryRunner.query(`
ALTER TABLE "transaction" DROP COLUMN "isSpent"
`);
await queryRunner.query(`
ALTER TABLE "transaction" DROP COLUMN "outputs"
`);
}

public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
DROP TABLE "transaction_output"
`);
await queryRunner.query(`
ALTER TABLE "transaction" ADD COLUMN "isSpent" boolean NOT NULL
`);
await queryRunner.query(`
ALTER TABLE "transaction" ADD COLUMN "outputs" text NOT NULL
`);
}
}
2 changes: 0 additions & 2 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { OperationStateModule } from '@/operation-state/operation-state.module';
import { ScheduleModule } from '@nestjs/schedule';
import { BlockProviderModule } from '@/block-data-providers/block-provider.module';
import { EventEmitterModule } from '@nestjs/event-emitter';
import { TransactionOutputModule } from '@/transaction-output/transaction-output.module';

@Module({
imports: [
Expand All @@ -35,7 +34,6 @@ import { TransactionOutputModule } from '@/transaction-output/transaction-output
SilentBlocksModule,
OperationStateModule,
BlockProviderModule,
TransactionOutputModule,
],
controllers: [AppController],
providers: [AppService],
Expand Down
10 changes: 6 additions & 4 deletions src/indexer/indexer.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Transaction } from '@/transactions/transaction.entity';
import { TransactionOutput as TransactionOutputEntity } from '@/transaction-output/transaction-output.entity';
import { TransactionOutput as TransactionOutputEntity } from '@/transactions/transaction-output.entity';
import { createTaggedHash, extractPubKeyFromScript } from '@/common/common';
import { publicKeyCombine, publicKeyTweakMul } from 'secp256k1';
import { Injectable } from '@nestjs/common';
Expand Down Expand Up @@ -40,8 +40,6 @@ export class IndexerService {
transaction.scanTweak = scanTweak.toString('hex');
transaction.outputs = eligibleOutputs;

console.log(transaction);

await manager.save(Transaction, transaction);
}
}
Expand All @@ -57,13 +55,17 @@ export class IndexerService {
})),
});

if (outputs.length == 0) {
return;
}

// Mark each output as spent
const spentOutputs = outputs.map((output) => ({
...output,
isSpent: true,
}));

await manager.save(spentOutputs);
await manager.save(TransactionOutputEntity, spentOutputs);
}

public deriveOutputsAndComputeScanTweak(
Expand Down
8 changes: 4 additions & 4 deletions src/silent-blocks/silent-blocks.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ export class SilentBlocksController {
@Get('hash/:blockHash')
async getSilentBlockByHash(
@Param('blockHash') blockHash: string,
@Query('unspent') unspent = 'false',
@Query('filterSpent') filterSpentFlag = 'false',
@Res() res: Response,
) {
// Convert unspent to boolean
const unspentFlag = unspent === 'true';
// Convert to boolean
const filterSpent = filterSpentFlag === 'true';

const buffer = await this.silentBlocksService.getSilentBlockByHash(
blockHash,
unspentFlag,
filterSpent,
);

res.set({
Expand Down
10 changes: 4 additions & 6 deletions src/silent-blocks/silent-blocks.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,20 @@ export class SilentBlocksService {
await this.transactionsService.getTransactionByBlockHeight(
blockHeight,
);
console.log("outputs length", transactions[0]);

return this.encodeSilentBlock(transactions);
}

async getSilentBlockByHash(
blockHash: string,
unspentFlag: boolean,
filterSpent: boolean,
): Promise<Buffer> {
let transactions =
await this.transactionsService.getTransactionByBlockHash(blockHash);

console.log("outputs length", transactions[0]);

if (unspentFlag) {
if (filterSpent) {
transactions = transactions.filter((transaction) =>
transaction.outputs.every((output) => output.isSpent),
transaction.outputs.some((output) => !output.isSpent),
);
}

Expand Down
8 changes: 0 additions & 8 deletions src/transaction-output/transaction-output.module.ts

This file was deleted.

12 changes: 9 additions & 3 deletions src/transactions/transaction.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ const mockTransactions: Transaction[] = [
pubKey: '51203e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1',
vout: 1,
value: 100000,
id: 0,
isSpent: false,
transaction: new Transaction(),
},
],
isSpent: false,
},
{
id: '2',
Expand All @@ -33,9 +35,11 @@ const mockTransactions: Transaction[] = [
pubKey: '51203e9fce73d4e77a4809908e3c3a2e54ee147b9312dc5044a193d1fc85de46e3c1',
vout: 2,
value: 100000,
id: 0,
isSpent: false,
transaction: new Transaction(),
},
],
isSpent: true,
},
{
id: '3',
Expand All @@ -49,9 +53,11 @@ const mockTransactions: Transaction[] = [
pubKey: '5120f4c2da807f89cb1501f1a77322a895acfb93c28e08ed2724d2beb8e44539ba38',
vout: 3,
value: 100000,
id: 0,
isSpent: false,
transaction: new Transaction(),
},
],
isSpent: false,
},
];

Expand Down
2 changes: 1 addition & 1 deletion src/transactions/transaction.entity.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { TransactionOutput } from '@/transaction-output/transaction-output.entity';
import { TransactionOutput } from '@/transactions/transaction-output.entity';
import { Column, Entity, OneToMany, PrimaryColumn } from 'typeorm';

@Entity()
Expand Down
7 changes: 5 additions & 2 deletions src/transactions/transactions.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TransactionsService } from '@/transactions/transactions.service';
import { Transaction } from '@/transactions/transaction.entity';
import {
Transaction,
TransactionOutput,
} from '@/transactions/transaction.entity';
import { TransactionController } from '@/transactions/transactions.controller';

@Module({
imports: [TypeOrmModule.forFeature([Transaction])],
imports: [TypeOrmModule.forFeature([Transaction, TransactionOutput])],
controllers: [TransactionController],
providers: [TransactionsService],
exports: [TransactionsService],
Expand Down
10 changes: 8 additions & 2 deletions src/transactions/transactions.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,17 @@ export class TransactionsService {
async getTransactionByBlockHeight(
blockHeight: number,
): Promise<Transaction[]> {
return this.transactionRepository.find({ where: { blockHeight } });
return this.transactionRepository.find({
where: { blockHeight },
relations: { outputs: true },
});
}

async getTransactionByBlockHash(blockHash: string): Promise<Transaction[]> {
return this.transactionRepository.find({ where: { blockHash }, relations: { outputs: true} });
return this.transactionRepository.find({
where: { blockHash },
relations: { outputs: true },
});
}

async saveTransaction(transaction: Transaction): Promise<Transaction> {
Expand Down
Binary file added ~/.silent-pay-indexer/db/database.sqlite
Binary file not shown.

0 comments on commit e5854bd

Please sign in to comment.