UNPKG

@btc-vision/btc-runtime

Version:

Bitcoin L1 Smart Contract Runtime for OP_NET. Build decentralized applications on Bitcoin using AssemblyScript and WebAssembly. Fully audited.

96 lines (78 loc) 3.64 kB
import { Address } from '../../types/Address'; import { TransactionInput, TransactionOutput } from './UTXO'; import { Potential } from '../../lang/Definitions'; import { BytesReader } from '../../buffer/BytesReader'; import { getInputsSize, getOutputsSize, inputs, outputs } from '../global'; import { TransactionDecoder } from '../decoders/TransactionDecoder'; import { ConsensusRules } from '../consensus/ConsensusRules'; import { ExtendedAddress } from '../../types/ExtendedAddress'; @final export class Transaction { public readonly consensus: ConsensusRules; /** * The `sender` is the immediate caller of this transaction, which may be a contract or a user. * It is always typed as `Address`, which may not be quantum-resistant. * * The `origin` is the original transaction signer (the "leftmost" entity in the call chain). * It is typed as `ExtendedAddress`, allowing for both Schnorr and ML-DSA keys (including quantum-resistant keys). * * This distinction is intentional: only the transaction originator may use quantum-resistant keys, * while intermediate contract callers are always standard addresses. This should be considered when * performing address verification or signature checks. */ public readonly sender: Address; /** * The `origin` is the original transaction signer (the "leftmost" entity in the call chain). * It is typed as `ExtendedAddress`, allowing for both Schnorr and ML-DSA keys (including quantum-resistant keys). * * This distinction is intentional: only the transaction originator may use quantum-resistant keys, * while intermediate contract callers are always standard addresses. This should be considered when * performing address verification or signature checks. * */ public readonly origin: ExtendedAddress; private readonly transactionDecoder: TransactionDecoder = new TransactionDecoder(); public constructor( sender: Address, // "immediate caller" origin: ExtendedAddress, // "leftmost thing in the call chain" public readonly txId: Uint8Array, public readonly hash: Uint8Array, consensusFlags: u64, ) { this.sender = sender; this.origin = origin; this.consensus = new ConsensusRules(consensusFlags); } private _inputs: Potential<TransactionInput[]> = null; public get inputs(): TransactionInput[] { if (!this._inputs) { const inputs = this.loadInputs(); this._inputs = inputs; return inputs; } return this._inputs as TransactionInput[]; } private _outputs: Potential<TransactionOutput[]> = null; public get outputs(): TransactionOutput[] { if (!this._outputs) { const outputs = this.loadOutputs(); this._outputs = outputs; return outputs; } return this._outputs as TransactionOutput[]; } private loadInputs(): TransactionInput[] { const inputsSize = getInputsSize(); const resultBuffer = new ArrayBuffer(inputsSize); inputs(resultBuffer); const reader = new BytesReader(Uint8Array.wrap(resultBuffer)); return this.transactionDecoder.readTransactionInputs(reader); } private loadOutputs(): TransactionOutput[] { const outputsSize = getOutputsSize(); const resultBuffer = new ArrayBuffer(outputsSize); outputs(resultBuffer); const reader = new BytesReader(Uint8Array.wrap(resultBuffer)); return this.transactionDecoder.readTransactionOutputs(reader); } }