Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion packages/library/src/hooks/TransactionFeeHook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,12 @@ export class TransactionFeeHook extends ProvableTransactionHook<TransactionFeeHo

public async start() {
this.persistedFeeAnalyzer = new RuntimeFeeAnalyzerService(this.runtime);
this.verifyConfig();
this.persistedFeeAnalyzer.config = this.config;
await this.persistedFeeAnalyzer.initializeFeeTree();
}

public get config() {
this.verifyConfig();
return super.config;
}

Expand Down
21 changes: 14 additions & 7 deletions packages/persistance/src/services/prisma/PrismaBlockStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
BlockStorage,
BlockWithResult,
BlockWithMaybeResult,
Tracer,
trace,
} from "@proto-kit/sequencer";
import { log } from "@proto-kit/common";
import {
Expand All @@ -33,7 +35,8 @@ export class PrismaBlockStorage
private readonly transactionResultMapper: TransactionExecutionResultMapper,
private readonly transactionMapper: TransactionMapper,
private readonly blockResultMapper: BlockResultMapper,
private readonly blockMapper: BlockMapper
private readonly blockMapper: BlockMapper,
@inject("Tracer") public readonly tracer: Tracer
) {}

private async getBlockByQuery(
Expand Down Expand Up @@ -76,6 +79,7 @@ export class PrismaBlockStorage
return (await this.getBlockByQuery({ hash }))?.block;
}

@trace("db.block.push", ([{ height }]) => ({ height: height.toString() }))
public async pushBlock(block: Block): Promise<void> {
log.trace(
"Pushing block to DB. Txs:",
Expand All @@ -96,12 +100,15 @@ export class PrismaBlockStorage

const { prismaClient } = this.connection;

await prismaClient.transaction.createMany({
data: block.transactions.map((txr) =>
this.transactionMapper.mapOut(txr.tx)
),
skipDuplicates: true,
});
// Note: We can assume all transactions are already in the DB here, because the
// mempool shares the same table as this one. But that could change in the future,
// then transaction have to be inserted-if-missing
// await prismaClient.transaction.createMany({
// data: block.transactions.map((txr) =>
// this.transactionMapper.mapOut(txr.tx)
// ),
// skipDuplicates: true,
// });

await prismaClient.block.create({
data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export class PrismaStateService implements AsyncStateService {
this.cache = [];
}

@trace("db.state.getMany")
public async getMany(keys: Field[]): Promise<StateEntry[]> {
const records = await this.connection.prismaClient.state.findMany({
where: {
Expand Down
19 changes: 19 additions & 0 deletions packages/sequencer/src/logging/ConsoleTracer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,25 @@ export class ConsoleTracer implements Tracer {
this.clearTraces();
}

activeManualTraceStack: [string, number][] = [];

public startTrace(name: string) {
const startTime = Date.now();

this.activeManualTraceStack.push([name, startTime]);
}

public endTrace() {
const [name, startTime] = this.activeManualTraceStack.pop()!;
const duration = Date.now() - startTime;

if (name in this.store) {
this.store[name].push({ duration });
} else {
this.store[name] = [{ duration }];
}
}

public async trace<T>(
name: string,
f: () => Promise<T>,
Expand Down
96 changes: 57 additions & 39 deletions packages/sequencer/src/mempool/PendingTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,45 +28,57 @@ export type UnsignedTransactionBody = {
};

export class UnsignedTransaction implements UnsignedTransactionBody {
public methodId: Field;
public readonly methodId: Field;

public nonce: UInt64;
public readonly nonce: UInt64;

public sender: PublicKey;
public readonly sender: PublicKey;

public argsFields: Field[];
public readonly argsFields: Field[];

public auxiliaryData: string[];
public readonly auxiliaryData: string[];

public isMessage: boolean;
public readonly isMessage: boolean;

public constructor(data: {
methodId: Field;
nonce: UInt64;
sender: PublicKey;
argsFields: Field[];
auxiliaryData: string[];
isMessage: boolean;
}) {
public constructor(
data: {
methodId: Field;
nonce: UInt64;
sender: PublicKey;
argsFields: Field[];
auxiliaryData: string[];
isMessage: boolean;
},
memoizedHash?: Field
) {
this.methodId = data.methodId;
this.nonce = data.nonce;
this.sender = data.sender;
this.argsFields = data.argsFields;
this.auxiliaryData = data.auxiliaryData;
this.isMessage = data.isMessage;

if (memoizedHash !== undefined) {
this.memoizedHash = memoizedHash;
}
}

public argsHash(): Field {
return Poseidon.hash(this.argsFields);
}

private memoizedHash?: Field = undefined;

public hash(): Field {
return Poseidon.hash([
this.methodId,
...this.sender.toFields(),
...this.nonce.toFields(),
this.argsHash(),
]);
if (this.memoizedHash === undefined) {
this.memoizedHash = Poseidon.hash([
this.methodId,
...this.sender.toFields(),
...this.nonce.toFields(),
this.argsHash(),
]);
}
return this.memoizedHash;
}

public getSignatureData(): Field[] {
Expand Down Expand Up @@ -124,29 +136,35 @@ export class PendingTransaction extends UnsignedTransaction {
public static fromJSON(
object: PendingTransactionJSONType
): PendingTransaction {
return new PendingTransaction({
methodId: Field.fromJSON(object.methodId),
nonce: UInt64.from(object.nonce),
sender: PublicKey.fromBase58(object.sender),
argsFields: object.argsFields.map((x) => Field.fromJSON(x)),
signature: Signature.fromJSON(object.signature),
auxiliaryData: object.auxiliaryData.slice(),
isMessage: object.isMessage,
});
return new PendingTransaction(
{
methodId: Field.fromJSON(object.methodId),
nonce: UInt64.from(object.nonce),
sender: PublicKey.fromBase58(object.sender),
argsFields: object.argsFields.map((x) => Field.fromJSON(x)),
signature: Signature.fromJSON(object.signature),
auxiliaryData: object.auxiliaryData.slice(),
isMessage: object.isMessage,
},
Field(object.hash)
);
}

public signature: Signature;

public constructor(data: {
methodId: Field;
nonce: UInt64;
sender: PublicKey;
signature: Signature;
argsFields: Field[];
auxiliaryData: string[];
isMessage: boolean;
}) {
super(data);
public constructor(
data: {
methodId: Field;
nonce: UInt64;
sender: PublicKey;
signature: Signature;
argsFields: Field[];
auxiliaryData: string[];
isMessage: boolean;
},
memoizedHash?: Field
) {
super(data, memoizedHash);
this.signature = data.signature;
}

Expand Down
4 changes: 1 addition & 3 deletions packages/sequencer/src/mempool/private/PrivateMempool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,7 @@ export class PrivateMempool
const success = await this.transactionStorage.pushUserTransaction(tx);
if (success) {
this.events.emit("mempool-transaction-added", tx);
log.trace(
`Transaction added to mempool: ${tx.hash().toString()} (${(await this.transactionStorage.getPendingUserTransactions()).length} transactions in mempool)`
);
log.trace(`Transaction added to mempool: ${tx.hash().toString()}`);
} else {
log.error(
`Transaction ${tx.hash().toString()} rejected: already exists in mempool`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,12 @@ export class BlockProductionService {

const lastResult = lastBlockWithResult.result;
const lastBlock = lastBlockWithResult.block;
const executionResults: TransactionExecutionResult[] = [];

const incomingMessagesList = new MinaActionsHashList(
Field(lastBlock.toMessagesHash)
);

let blockState: BlockTrackers = {
const blockState: BlockTrackers = {
blockHashRoot: Field(lastResult.blockHashRoot),
eternalTransactionsList: new TransactionHashList(
lastBlock.toEternalTransactionsHash
Expand All @@ -133,28 +132,13 @@ export class BlockProductionService {
UntypedStateTransition.fromStateTransition(transition)
);

for (const tx of transactions) {
try {
// Create execution trace
const [newState, executionTrace] =
// eslint-disable-next-line no-await-in-loop
await this.transactionExecutionService.createExecutionTrace(
stateService,
tx,
networkState,
blockState
);

blockState = newState;

// Push result to results and transaction onto bundle-hash
executionResults.push(executionTrace);
} catch (error) {
if (error instanceof Error) {
log.error("Error in inclusion of tx, skipping", error);
}
}
}
const [newBlockState, executionResults] =
await this.transactionExecutionService.createExecutionTraces(
stateService,
transactions,
networkState,
blockState
);

const previousBlockHash =
lastResult.blockHash === 0n ? undefined : Field(lastResult.blockHash);
Expand All @@ -168,9 +152,10 @@ export class BlockProductionService {

const block: Omit<Block, "hash"> = {
transactions: executionResults,
transactionsHash: blockState.transactionList.commitment,
transactionsHash: newBlockState.transactionList.commitment,
fromEternalTransactionsHash: lastBlock.toEternalTransactionsHash,
toEternalTransactionsHash: blockState.eternalTransactionsList.commitment,
toEternalTransactionsHash:
newBlockState.eternalTransactionsList.commitment,
height:
lastBlock.hash.toBigInt() !== 0n ? lastBlock.height.add(1) : Field(0),
fromBlockHashRoot: Field(lastResult.blockHashRoot),
Expand Down
Loading