Skip to content

Commit

Permalink
change to dynamically computed transactionviews
Browse files Browse the repository at this point in the history
  • Loading branch information
Valentine1898 committed Mar 11, 2024
1 parent 5abc4a5 commit d0b527c
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,14 @@ describe('BroadcastTransaction request handler', () => {

mockTendermint.broadcastTx?.mockResolvedValue(transactionIdData);
txSubNext.mockResolvedValueOnce({
value: { value: {id: transactionIdData, height: detectionHeight, transaction: transactionData}, table: 'TRANSACTIONS' },
value: {
value: new TransactionInfo({
id: transactionIdData,
height: detectionHeight,
transaction: transactionData,
}).toJson(),
table: 'TRANSACTIONS',
},
});

broadcastTransactionRequest.awaitDetection = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ConnectError, Code } from '@connectrpc/connect';

import { sha256Hash } from '@penumbra-zone/crypto-web';
import { uint8ArrayToHex } from '@penumbra-zone/types';
import { TransactionInfo } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/view/v1/view_pb';

export const broadcastTransaction: Impl['broadcastTransaction'] = async function* (req, ctx) {
const services = ctx.values.get(servicesCtx);
Expand Down Expand Up @@ -39,8 +40,9 @@ export const broadcastTransaction: Impl['broadcastTransaction'] = async function

// Wait until DB records a new transaction with this id
for await (const { value } of subscription) {
const detectionId = TransactionId.fromJson(value.id);
const detectionHeight = value.height;
const transactionRecord = TransactionInfo.fromJson(value);
const detectionId = transactionRecord.id;
const detectionHeight = transactionRecord.height;
if (id.equals(detectionId)) {
yield {
status: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ export const transactionInfoByHash: Impl['transactionInfoByHash'] = async (req,
if (!req.id) throw new ConnectError('Missing transaction ID in request', Code.InvalidArgument);

const { transaction, height } =
(await indexedDb.getTransaction(req.id)) || (await querier.tendermint.getTransaction(req.id));
(await indexedDb.getTransaction(req.id)) ?? (await querier.tendermint.getTransaction(req.id));

if (!transaction) throw new ConnectError('Transaction not available', Code.NotFound);

const { txp: perspective, txv: view } = await generateTransactionInfo(
fullViewingKey,
transaction,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@ import { createContextValues, createHandlerContext, HandlerContext } from '@conn
import { beforeEach, describe, expect, test, vi } from 'vitest';

import {
TransactionInfo,
TransactionInfoRequest,
TransactionInfoResponse,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/view/v1/view_pb';
import { IndexedDbMock, MockServices, ViewServerMock } from '../test-utils';
import { Services } from '@penumbra-zone/services';
import { transactionInfo } from './transaction-info';
import { TransactionRecord } from '@penumbra-zone/types';
import { Transaction } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/transaction/v1/transaction_pb';
import { TransactionId } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/txhash/v1/txhash_pb';

const mockTransactionInfo = vi.hoisted(() => vi.fn());
vi.mock('@penumbra-zone/wasm', () => ({
Expand Down Expand Up @@ -117,33 +115,33 @@ describe('TransactionInfo request handler', () => {
});
});

const testData: TransactionRecord[] = [
{
height: 222n,
id: TransactionId.fromJson({
const testData: TransactionInfo[] = [
TransactionInfo.fromJson({
height: '222',
id: {
inner: '1MI8IG5D3MQj3s1j0MXTwCQtAaVbwTlPkW8Qdz1EVIo=',
}),
transaction: Transaction.fromJson({}),
},
{
height: 1000n,
id: TransactionId.fromJson({
},
transaction: {},
}),
TransactionInfo.fromJson({
height: '1000',
id: {
inner: '2MI8IG5D3MQj3s1j0MXTwCQtAaVbwTlPkW8Qdz1EVIo=',
}),
transaction: Transaction.fromJson({}),
},
{
height: 2525n,
id: TransactionId.fromJson({
},
transaction: {},
}),
TransactionInfo.fromJson({
height: '2525',
id: {
inner: '3MI8IG5D3MQj3s1j0MXTwCQtAaVbwTlPkW8Qdz1EVIo=',
}),
transaction: Transaction.fromJson({}),
},
{
height: 12255n,
id: TransactionId.fromJson({
},
transaction: {},
}),
TransactionInfo.fromJson({
height: '12255',
id: {
inner: '4MI8IG5D3MQj3s1j0MXTwCQtAaVbwTlPkW8Qdz1EVIo=',
}),
transaction: Transaction.fromJson({}),
},
},
transaction: {},
}),
];
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ export const transactionInfo: Impl['transactionInfo'] = async function* (req, ct

for await (const txRecord of indexedDb.iterateTransactions()) {
// filter transactions between startHeight and endHeight, inclusive
if (txRecord.height < req.startHeight || (req.endHeight && txRecord.height > req.endHeight))
if (
!txRecord.transaction ||
txRecord.height < req.startHeight ||
(req.endHeight && txRecord.height > req.endHeight)
)
continue;

const { txp: perspective, txv: view } = await generateTransactionInfo(
Expand Down
30 changes: 17 additions & 13 deletions packages/storage/src/indexed-db/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
PenumbraDb,
ScanBlockResult,
StateCommitmentTree,
TransactionRecord,
uint8ArrayToBase64,
uint8ArrayToHex,
} from '@penumbra-zone/types';
Expand All @@ -25,6 +24,7 @@ import {
NotesForVotingResponse,
SpendableNoteRecord,
SwapRecord,
TransactionInfo,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/view/v1/view_pb';
import {
AssetId,
Expand Down Expand Up @@ -214,31 +214,35 @@ export class IndexedDb implements IndexedDbInterface {
start: async cont => {
let cursor = await this.db.transaction('TRANSACTIONS').store.openCursor();
while (cursor) {
cont.enqueue(cursor.value);
cont.enqueue(TransactionInfo.fromJson(cursor.value));
cursor = await cursor.continue();
}
cont.close();
},
});
}

async saveTransaction(id: TransactionId, height: bigint, tx: Transaction): Promise<void> {
const txRecord: TransactionRecord = {
id: id.toJson() as Jsonified<TransactionId>,
height: height,
tx: tx.toJson() as Jsonified<Transaction>,
};
async saveTransaction(
id: TransactionId,
height: bigint,
transaction: Transaction,
): Promise<void> {
const tx = new TransactionInfo({
id,
height,
transaction,
});
await this.u.update({
table: 'TRANSACTIONS',
value: txRecord,
value: tx.toJson() as Jsonified<TransactionInfo>,
});
}

async getTransaction(txId: TransactionId): Promise<TransactionRecord | undefined> {
async getTransaction(txId: TransactionId): Promise<TransactionInfo | undefined> {
const key = uint8ArrayToBase64(txId.inner);
const transactionRecord = await this.db.get('TRANSACTIONS', key);
if (!transactionRecord) return undefined;
return transactionRecord;
const jsonRecord = await this.db.get('TRANSACTIONS', key);
if (!jsonRecord) return undefined;
return TransactionInfo.fromJson(jsonRecord);
}

async getFmdParams(): Promise<FmdParameters | undefined> {
Expand Down
5 changes: 1 addition & 4 deletions packages/storage/src/indexed-db/indexed-db.test-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { Metadata } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/
import {
SpendableNoteRecord,
SwapRecord,
TransactionInfo,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/view/v1/view_pb';
import {
Position,
Expand Down Expand Up @@ -716,6 +715,4 @@ export const epoch2 = new Epoch({
export const epoch3 = new Epoch({
index: 2n,
startHeight: 200n,
});

export class transactionInfo {}
});
20 changes: 10 additions & 10 deletions packages/storage/src/indexed-db/indexed-db.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { FmdParameters } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/
import {
SpendableNoteRecord,
SwapRecord,
TransactionInfo,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/view/v1/view_pb';
import { IdbUpdate, PenumbraDb, TransactionRecord } from '@penumbra-zone/types';
import { IdbUpdate, PenumbraDb } from '@penumbra-zone/types';
import { beforeEach, describe, expect, it } from 'vitest';
import { IndexedDb } from '.';
import {
Expand Down Expand Up @@ -41,7 +42,6 @@ import {
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/dex/v1/dex_pb';
import { Metadata } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb';
import { localAssets } from '@penumbra-zone/constants';
import { Transaction } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/transaction/v1/transaction_pb';

describe('IndexedDb', () => {
// uses different wallet ids so no collisions take place
Expand Down Expand Up @@ -137,9 +137,9 @@ describe('IndexedDb', () => {
expect(assets.length).toBe(1 + localAssets.length);

await db.saveTransaction(transactionId, 1000n, transaction);
const txs: TransactionRecord[] = [];
const txs: TransactionInfo[] = [];
for await (const tx of db.iterateTransactions()) {
txs.push(tx);
txs.push(tx as TransactionInfo);
}
expect(txs.length).toBe(1);

Expand Down Expand Up @@ -179,9 +179,9 @@ describe('IndexedDb', () => {
}
expect(assetsAfterClear.length).toBe(0);

const txsAfterClean: TransactionRecord[] = [];
const txsAfterClean: TransactionInfo[] = [];
for await (const tx of db.iterateTransactions()) {
txsAfterClean.push(tx);
txsAfterClean.push(tx as TransactionInfo);
}
expect(txsAfterClean.length).toBe(0);
expect(await db.getFullSyncHeight()).toBeUndefined();
Expand Down Expand Up @@ -314,19 +314,19 @@ describe('IndexedDb', () => {
await db.saveTransaction(transactionId, 1000n, transaction);

const savedTransaction = await db.getTransaction(transactionId);
expect(transaction.equals(Transaction.fromJson(savedTransaction?.tx!))).toBeTruthy();
expect(transaction.equals(savedTransaction?.transaction)).toBeTruthy();
});

it('should be able to set/get all', async () => {
const db = await IndexedDb.initialize({ ...generateInitialProps() });

await db.saveTransaction(transactionId, 1000n, transaction);
const savedTransactions: TransactionRecord[] = [];
const savedTransactions: TransactionInfo[] = [];
for await (const tx of db.iterateTransactions()) {
savedTransactions.push(tx);
savedTransactions.push(tx as TransactionInfo);
}
expect(savedTransactions.length === 1).toBeTruthy();
expect(transaction.equals(Transaction.fromJson(savedTransactions[0]?.tx!))).toBeTruthy();
expect(transaction.equals(savedTransactions[0]?.transaction)).toBeTruthy();
});
});

Expand Down
15 changes: 5 additions & 10 deletions packages/types/src/indexed-db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
NotesForVotingResponse,
SpendableNoteRecord,
SwapRecord,
TransactionInfo,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/view/v1/view_pb';
import {
AssetId,
Expand Down Expand Up @@ -60,8 +61,8 @@ export interface IndexedDbInterface {
saveSpendableNote(note: SpendableNoteRecord): Promise<void>;
iterateSpendableNotes(): AsyncGenerator<SpendableNoteRecord, void>;
saveTransaction(id: TransactionId, height: bigint, tx: Transaction): Promise<void>;
getTransaction(txId: TransactionId): Promise<TransactionRecord | undefined>;
iterateTransactions(): AsyncGenerator<TransactionRecord, void>;
getTransaction(txId: TransactionId): Promise<TransactionInfo | undefined>;
iterateTransactions(): AsyncGenerator<TransactionInfo, void>;
getAssetsMetadata(assetId: AssetId): Promise<Metadata | undefined>;
saveAssetsMetadata(metadata: Metadata): Promise<void>;
iterateAssetsMetadata(): AsyncGenerator<Metadata, void>;
Expand Down Expand Up @@ -123,8 +124,8 @@ export interface PenumbraDb extends DBSchema {
value: Jsonified<FmdParameters>;
};
TRANSACTIONS: {
key: string; // base64 TransactionRecord['id']['inner'];
value: Jsonified<TransactionRecord>;
key: string; // base64 TransactionInfo['id']['inner'];
value: Jsonified<TransactionInfo>; // TransactionInfo with undefined view and perspective
};
// ======= Json serialized values =======
// Allows wasm crate to directly deserialize
Expand Down Expand Up @@ -178,12 +179,6 @@ export interface PositionRecord {
position: Jsonified<Position>; // Position
}

export interface TransactionRecord {
id: TransactionId;
height: bigint;
transaction: Transaction;
}

export type Tables = Record<string, StoreNames<PenumbraDb>>;
export type PenumbraStoreNames = StoreNames<PenumbraDb>;

Expand Down

0 comments on commit d0b527c

Please sign in to comment.