@btc-vision/transaction
Version:
OPNet transaction library allows you to create and sign transactions for the OPNet network.
106 lines (105 loc) • 4.35 kB
JavaScript
import { stringToBuffer } from '../utils/StringToBuffer.js';
import { Address } from '../keypair/Address.js';
import { EpochValidator } from './validator/EpochValidator.js';
import { BinaryWriter } from '../buffer/BinaryWriter.js';
import { MessageSigner } from '../keypair/MessageSigner.js';
export class ChallengeVerification {
constructor(data) {
this.epochHash = stringToBuffer(data.epochHash);
this.epochRoot = stringToBuffer(data.epochRoot);
this.targetHash = stringToBuffer(data.targetHash);
this.targetChecksum = stringToBuffer(data.targetChecksum);
this.startBlock = BigInt(data.startBlock);
this.endBlock = BigInt(data.endBlock);
this.proofs = Object.freeze(data.proofs.map((proof) => stringToBuffer(proof)));
}
}
export class ChallengeSubmission {
constructor(data, epochNumber) {
this.epochNumber = epochNumber;
this.publicKey = Address.fromString(data.publicKey);
this.solution = stringToBuffer(data.solution);
this.graffiti = data.graffiti ? stringToBuffer(data.graffiti) : undefined;
this.signature = stringToBuffer(data.signature);
}
verifySignature() {
const signatureDataWriter = new BinaryWriter();
signatureDataWriter.writeAddress(this.publicKey);
signatureDataWriter.writeU64(this.epochNumber);
signatureDataWriter.writeBytes(this.solution);
if (this.graffiti) {
signatureDataWriter.writeBytes(this.graffiti);
}
const buffer = signatureDataWriter.getBuffer();
return MessageSigner.verifySignature(this.publicKey, buffer, this.signature);
}
}
export class ChallengeSolution {
constructor(data) {
this.epochNumber = BigInt(data.epochNumber);
this.publicKey = Address.fromString(data.publicKey);
this.solution = stringToBuffer(data.solution);
this.salt = stringToBuffer(data.salt);
this.graffiti = stringToBuffer(data.graffiti);
this.difficulty = data.difficulty;
this.verification = new ChallengeVerification(data.verification);
this.submission = data.submission
? new ChallengeSubmission(data.submission, this.epochNumber + 2n)
: data.submission;
}
static validateRaw(data) {
return EpochValidator.validateEpochWinner(data);
}
verifySubmissionSignature() {
if (!this.submission) {
throw new Error('No submission provided in request.');
}
return this.submission.verifySignature();
}
getSubmission() {
if (!this.submission) {
return;
}
if (!this.verifySubmissionSignature()) {
throw new Error('Invalid submission signature.');
}
return this.submission;
}
verify() {
return EpochValidator.validateChallengeSolution(this);
}
toBuffer() {
return this.solution;
}
toHex() {
return '0x' + this.solution.toString('hex');
}
toRaw() {
return {
epochNumber: this.epochNumber.toString(),
publicKey: this.publicKey.toHex(),
solution: this.toHex(),
salt: '0x' + this.salt.toString('hex'),
graffiti: '0x' + this.graffiti.toString('hex'),
difficulty: this.difficulty,
verification: {
epochHash: '0x' + this.verification.epochHash.toString('hex'),
epochRoot: '0x' + this.verification.epochRoot.toString('hex'),
targetHash: '0x' + this.verification.targetHash.toString('hex'),
targetChecksum: '0x' + this.verification.targetChecksum.toString('hex'),
startBlock: this.verification.startBlock.toString(),
endBlock: this.verification.endBlock.toString(),
proofs: this.verification.proofs.map((p) => '0x' + p.toString('hex')),
},
};
}
calculateSolution() {
return EpochValidator.calculateSolution(this.verification.targetChecksum, this.publicKey.toBuffer(), this.salt);
}
checkDifficulty(minDifficulty) {
return EpochValidator.checkDifficulty(this.solution, this.verification.targetHash, minDifficulty);
}
getMiningTargetBlock() {
return EpochValidator.getMiningTargetBlock(this.epochNumber);
}
}