@btc-vision/transaction
Version:
OPNet transaction library allows you to create and sign transactions for the OPNet network.
86 lines • 3.75 kB
JavaScript
import { crypto, networks, opcodes, script, } from '@btc-vision/bitcoin';
import { Generator } from '../Generator.js';
import { Features } from '../Features.js';
import { BinaryWriter } from '../../buffer/BinaryWriter.js';
export const OPNET_DEPLOYMENT_VERSION = 0x00;
export const versionBuffer = Uint8Array.from([OPNET_DEPLOYMENT_VERSION]);
export class DeploymentGenerator extends Generator {
constructor(senderPubKey, contractSaltPubKey, network = networks.bitcoin) {
super(senderPubKey, contractSaltPubKey, network);
}
/**
* Compile a bitcoin script representing a contract deployment
* @param {Uint8Array} contractBytecode - The contract bytecode
* @param {Uint8Array} contractSalt - The contract salt
* @param {ChallengeSolution} challenge - The challenge for reward
* @param {bigint} maxPriority - The maximum priority for the contract
* @param {Uint8Array} [calldata] - The calldata to be passed to the contract
* @param {Feature<Features>[]} [features] - Optional features to include in the script
* @returns {Uint8Array} - The compiled script
*/
compile(contractBytecode, contractSalt, challenge, maxPriority, calldata, features) {
const asm = this.getAsm(contractBytecode, contractSalt, challenge, maxPriority, calldata, features);
const compiled = script.compile(asm);
/**
* Verify that the script can be decompiled
*/
const decompiled = script.decompile(compiled);
if (!decompiled) {
throw new Error('Failed to decompile script??');
}
return compiled;
}
getAsm(contractBytecode, contractSalt, challenge, maxPriority, calldata, featuresRaw) {
if (!this.contractSaltPubKey)
throw new Error('Contract salt public key not set');
const dataChunks = this.splitBufferIntoChunks(contractBytecode);
const calldataChunks = calldata ? this.splitBufferIntoChunks(calldata) : [];
const featuresList = [];
const featureData = [];
if (featuresRaw && featuresRaw.length) {
const features = featuresRaw.sort((a, b) => a.priority - b.priority);
const finalBuffer = new BinaryWriter();
for (let i = 0; i < features.length; i++) {
const feature = features[i];
featuresList.push(feature.opcode);
this.encodeFeature(feature, finalBuffer);
}
featureData.push(...this.splitBufferIntoChunks(new Uint8Array(finalBuffer.getBuffer())));
}
const compiledData = [
this.getHeader(maxPriority, featuresList),
opcodes.OP_TOALTSTACK,
// CHALLENGE PREIMAGE FOR REWARD,
challenge.publicKey.toBuffer(),
opcodes.OP_TOALTSTACK,
challenge.solution,
opcodes.OP_TOALTSTACK,
this.xSenderPubKey,
opcodes.OP_DUP,
opcodes.OP_HASH256,
crypto.hash256(this.xSenderPubKey),
opcodes.OP_EQUALVERIFY,
opcodes.OP_CHECKSIGVERIFY,
this.contractSaltPubKey,
opcodes.OP_CHECKSIGVERIFY,
opcodes.OP_HASH256,
crypto.hash256(contractSalt),
opcodes.OP_EQUALVERIFY,
opcodes.OP_DEPTH,
opcodes.OP_1,
opcodes.OP_NUMEQUAL,
opcodes.OP_IF,
Generator.MAGIC,
...featureData,
opcodes.OP_0,
...calldataChunks,
opcodes.OP_1NEGATE,
...dataChunks,
opcodes.OP_ELSE,
opcodes.OP_1,
opcodes.OP_ENDIF,
];
return compiledData.flat();
}
}
//# sourceMappingURL=DeploymentGenerator.js.map