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
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import { OPNetConsensus } from '../../../../poc/configurations/OPNetConsensus.js
const EXPIRED_TRANSACTION_ERROR: string =
'Transaction was pending in the mempool for too long. It is no longer valid.';

const MINER_SOLUTION_INVALID: string =
'The provided solution does not match any of the allowed challenges for the miner. The transaction is no longer valid.';

const INVALID_MINER_CHALLENGE_ERROR: string =
'The provided miner address does not have a valid challenge solution.';

Expand All @@ -37,17 +40,19 @@ export class TransactionFactory {
// return;
//}

//console.log('allowedChallenges', allowedChallenges, 'miner', miner, toHex(miner));

const hasMiner = allowedChallenges.solutions.get(miner);
if (!hasMiner) {
throw new Error(EXPIRED_TRANSACTION_ERROR);
}

const hasSolution = hasMiner.some((challenge) => {
const hasSolution = hasMiner.some((challenge: Uint8Array) => {
return equals(challenge, preimage);
});

if (!hasSolution) {
throw new Error(EXPIRED_TRANSACTION_ERROR);
throw new Error(MINER_SOLUTION_INVALID);
}

if (OPNetConsensus.allowUnsafeSignatures) {
Expand Down
13 changes: 9 additions & 4 deletions src/src/poc/mempool/manager/Mempool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import {
} from '../../../threading/interfaces/thread-messages/messages/api/RPCMessage.js';
import { BitcoinRPCThreadMessageType } from '../../../blockchain-indexer/rpc/thread/messages/BitcoinRPCThreadMessage.js';
import { OPNetBroadcastData } from '../../../threading/interfaces/thread-messages/messages/api/BroadcastTransactionOPNet.js';
import { TransactionVerifierManager } from '../transaction/TransactionVerifierManager.js';
import {
InvalidTransaction,
TransactionVerifierManager,
} from '../transaction/TransactionVerifierManager.js';
import { BitcoinRPC, FeeEstimation, SmartFeeEstimation } from '@btc-vision/bitcoin-rpc';
import { Config } from '../../../config/Config.js';
import { MempoolRepository } from '../../../db/repositories/MempoolRepository.js';
Expand Down Expand Up @@ -200,7 +203,7 @@ export class Mempool extends Logger {

private async watchBlockchain(): Promise<void> {
this.blockchainInformationRepository.watchBlockChanges(async (blockHeight: bigint) => {
if (OPNetConsensus.getBlockHeight() < blockHeight) {
if (OPNetConsensus.getBlockHeight() <= blockHeight) {
await this.onBlockChange(blockHeight);
}

Expand All @@ -219,6 +222,8 @@ export class Mempool extends Logger {
try {
OPNetConsensus.setBlockHeight(blockHeight);

this.log(`[MEM] Block changed to height ${blockHeight}`);

await this.transactionVerifier.onBlockChange(blockHeight);

/*if (Config.MEMPOOL.ENABLE_BLOCK_PURGE) {
Expand Down Expand Up @@ -382,10 +387,10 @@ export class Mempool extends Logger {
}

const decodedTransaction = await this.transactionVerifier.verify(transaction);
if (!decodedTransaction) {
if (!decodedTransaction || !decodedTransaction.success) {
return {
success: false,
result: 'Could not decode transaction.',
result: `Could not decode transaction (${(decodedTransaction as InvalidTransaction).error})`,
};
}

Expand Down
17 changes: 14 additions & 3 deletions src/src/poc/mempool/transaction/TransactionVerifierManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,19 @@ export interface PSBTDecodedData {
readonly estimatedFees: bigint;
}

export interface IKnownTransaction {
export interface MempoolTransaction {
readonly success: boolean;
}

export interface IKnownTransaction extends MempoolTransaction {
readonly type: TransactionTypes;
readonly version: Consensus;
}

export interface InvalidTransaction extends MempoolTransaction {
readonly error: string;
}

export interface KnownPSBTObject extends IKnownTransaction {
readonly psbt: Psbt;
readonly data: PSBTDecodedData;
Expand Down Expand Up @@ -66,7 +74,7 @@ export class TransactionVerifierManager extends Logger {
public async verify(
tx: IMempoolTransactionObj,
txData?: TransactionData,
): Promise<IKnownTransaction | false> {
): Promise<IKnownTransaction | InvalidTransaction> {
const psbtType: TransactionTypes = tx.data[0];

const verificator = this.verificator.find((v) =>
Expand All @@ -82,7 +90,10 @@ export class TransactionVerifierManager extends Logger {
}

if (!psbtOrTransaction) {
return false;
return {
success: false,
error: 'PSBTs are not allowed.',
};
}

return await verificator.verify(tx, psbtOrTransaction, txData);
Expand Down
7 changes: 5 additions & 2 deletions src/src/poc/mempool/verificator/TransactionVerifier.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { ConfigurableDBManager, Logger } from '@btc-vision/bsi-common';
import { TransactionTypes } from '../transaction/TransactionTypes.js';
import { Network, networks, Psbt, Transaction } from '@btc-vision/bitcoin';
import { IKnownTransaction } from '../transaction/TransactionVerifierManager.js';
import {
IKnownTransaction,
InvalidTransaction,
} from '../transaction/TransactionVerifierManager.js';
import { IMempoolTransactionObj } from '../../../db/interfaces/IMempoolTransaction.js';
import { BitcoinRPC, TransactionData } from '@btc-vision/bitcoin-rpc';

Expand Down Expand Up @@ -35,7 +38,7 @@ export abstract class TransactionVerifier<
tx: IMempoolTransactionObj,
data: Psbt | Transaction,
txData?: TransactionData,
): Promise<IKnownTransaction | false>;
): Promise<IKnownTransaction | InvalidTransaction>;

protected abstract onBlockChange(blockHeight: bigint): void | Promise<void>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ import { TransactionVerifier } from '../../TransactionVerifier.js';
import { TransactionTypes } from '../../../transaction/TransactionTypes.js';
import { Network, networks, toHex, Transaction } from '@btc-vision/bitcoin';
import { ConfigurableDBManager } from '@btc-vision/bsi-common';
import { KnownTransaction } from '../../../transaction/TransactionVerifierManager.js';
import { InvalidTransaction, KnownTransaction, } from '../../../transaction/TransactionVerifierManager.js';
import { Config } from '../../../../../config/Config.js';
import { TransactionFactory } from '../../../../../blockchain-indexer/processor/transaction/transaction-factory/TransactionFactory.js';
import {
TransactionFactory
} from '../../../../../blockchain-indexer/processor/transaction/transaction-factory/TransactionFactory.js';
import { IMempoolTransactionObj } from '../../../../../db/interfaces/IMempoolTransaction.js';
import { TransactionData, VOut } from '@btc-vision/bitcoin-rpc/src/rpc/types/BlockData.js';
import { BitcoinRPC } from '@btc-vision/bitcoin-rpc';
Expand All @@ -14,10 +16,18 @@ import { OPNetConsensus } from '../../../../configurations/OPNetConsensus.js';
import { ChallengeSolution } from '../../../../../blockchain-indexer/processor/interfaces/TransactionPreimage.js';
import { AddressMap } from '@btc-vision/transaction';
import { EpochRepository } from '../../../../../db/repositories/EpochRepository.js';
import { OPNetTransactionTypes } from '../../../../../blockchain-indexer/processor/transaction/enums/OPNetTransactionTypes.js';
import { Transaction as OPNetDecodedTransaction } from '../../../../../blockchain-indexer/processor/transaction/Transaction.js';
import { InteractionTransaction } from '../../../../../blockchain-indexer/processor/transaction/transactions/InteractionTransaction.js';
import { DeploymentTransaction } from '../../../../../blockchain-indexer/processor/transaction/transactions/DeploymentTransaction.js';
import {
OPNetTransactionTypes
} from '../../../../../blockchain-indexer/processor/transaction/enums/OPNetTransactionTypes.js';
import {
Transaction as OPNetDecodedTransaction
} from '../../../../../blockchain-indexer/processor/transaction/Transaction.js';
import {
InteractionTransaction
} from '../../../../../blockchain-indexer/processor/transaction/transactions/InteractionTransaction.js';
import {
DeploymentTransaction
} from '../../../../../blockchain-indexer/processor/transaction/transactions/DeploymentTransaction.js';

const EMPTY_BLOCK_HASH = toHex(new Uint8Array(32));

Expand All @@ -34,6 +44,9 @@ export class BitcoinTransactionVerificatorV2 extends TransactionVerifier<Transac
legacyPublicKeys: new AddressMap(),
});

private blockChangeQueue: Promise<void> = Promise.resolve();
private currentSolutionsHeight: bigint = -1n;

public constructor(
db: ConfigurableDBManager,
rpc: BitcoinRPC,
Expand All @@ -52,11 +65,26 @@ export class BitcoinTransactionVerificatorV2 extends TransactionVerifier<Transac
return this._epochRepository;
}

public async onBlockChange(blockHeight: bigint): Promise<void> {
public onBlockChange(blockHeight: bigint): Promise<void> {
this.blockChangeQueue = this.blockChangeQueue.then(async () => {
if (blockHeight === this.currentSolutionsHeight) {
return;
}

this.allowedChallenges =
this.epochRepository.getChallengeSolutionsAtHeight(blockHeight);
await this.allowedChallenges;
this.currentSolutionsHeight = blockHeight;
});

return this.blockChangeQueue;
}

/*public async onBlockChange(blockHeight: bigint): Promise<void> {
await this.allowedChallenges; // Don't flood the database on quick block changes

this.allowedChallenges = this.epochRepository.getChallengeSolutionsAtHeight(blockHeight);
}
}*/

public createRepositories(): void {
if (!this.db || !this.db.db) {
Expand All @@ -70,10 +98,11 @@ export class BitcoinTransactionVerificatorV2 extends TransactionVerifier<Transac
transaction: IMempoolTransactionObj,
data: Transaction,
txData?: TransactionData,
): Promise<KnownTransaction | false> {
let tx: KnownTransaction | false = false;
): Promise<KnownTransaction | InvalidTransaction> {
let tx: KnownTransaction | InvalidTransaction;
try {
const solutions = await this.allowedChallenges;

const decoded = !txData ? this.toRawTransactionData(data) : txData;
const opnetDecodedTransaction = this.transactionFactory.parseTransaction(
decoded,
Expand All @@ -84,6 +113,7 @@ export class BitcoinTransactionVerificatorV2 extends TransactionVerifier<Transac
);

tx = {
success: true,
type: this.getTxVersion(data.version),
version: OPNetConsensus.consensus.CONSENSUS,
transaction: opnetDecodedTransaction,
Expand All @@ -105,9 +135,15 @@ export class BitcoinTransactionVerificatorV2 extends TransactionVerifier<Transac
);
}
} catch (e) {
const error = (e as Error).message;
if (Config.DEV_MODE) {
this.error(`Error verifying Bitcoin Transaction V2: ${(e as Error).message}`);
this.error(`Error verifying Bitcoin Transaction V2: ${error}`);
}

tx = {
success: false,
error: error,
};
}

return tx;
Expand Down