codenlighten/scrypt
0
1---2sidebar_position: 23---4 5# ScriptContext6 7In the UTXO model, the context of validating a smart contract is the UTXO containing it and the transaction spending it, including its inputs and outputs. In the following example, when the second of input of transaction `tx1` (2 inputs and 2 outputs) is spending the second output of `tx0` (3 inputs and 3 outputs), the context for the smart contract in the latter output is roughly the UTXO and `tx1` circled in red.89 10The context only contains local information, different from account-based blockchains whose context consists of the global state of the entire blockchain (as in Ethereum). A single shared global state across all smart contracts kills scalability, since they all have to sequentially processed due to potential race conditions.11 12This context is expressed in the `ScriptContext` interface.13```ts14export interface ScriptContext {15 /** version number of [transaction]{@link https://wiki.bitcoinsv.io/index.php/Bitcoin_Transactions#General_format_of_a_Bitcoin_transaction} */16 version: ByteString,17 /** the specific UTXO spent by this transaction input */18 utxo: UTXO,19 /** double-SHA256 hash of the serialization of some/all input outpoints, see [hashPrevouts]{@link https://github.com/bitcoin-sv/bitcoin-sv/blob/master/doc/abc/replay-protected-sighash.md#hashprevouts} */20 hashPrevouts: ByteString,21 /** double-SHA256 hash of the serialization of some/all input sequence values, see [hashSequence]{@link https://github.com/bitcoin-sv/bitcoin-sv/blob/master/doc/abc/replay-protected-sighash.md#hashsequence} */22 hashSequence: ByteString,23 /** sequence number of [transaction input]{@link https://wiki.bitcoinsv.io/index.php/Bitcoin_Transactions#Format_of_a_Transaction_Input} */24 sequence: bigint,25 /** double-SHA256 hash of the serialization of some/all output amount with its locking script, see [hashOutputs]{@link https://github.com/bitcoin-sv/bitcoin-sv/blob/master/doc/abc/replay-protected-sighash.md#hashoutputs} */26 hashOutputs: ByteString,27 /** locktime of [transaction]{@link https://wiki.bitcoinsv.io/index.php/Bitcoin_Transactions#General_format_of_a_Bitcoin_transaction} */28 locktime: bigint,29 /** [SIGHASH flag]{@link https://wiki.bitcoinsv.io/index.php/SIGHASH_flags} used by this input */30 sigHashType: SigHashType,31}32 33export interface UTXO {34 /** locking script */35 script: ByteString,36 /** amount in satoshis */37 value: bigint,38 /** outpoint referenced by this UTXO */39 outpoint: Outpoint,40}41 42export interface Outpoint {43 /** txid of the transaction holding the output */44 txid: ByteString,45 /** index of the specific output */46 outputIndex: bigint,47}48```49 50The table shows the meaning of each field of the `ScriptContext` structure.51 52| Field | Description |53| ------------- | ------------- |54| version | version of the transaction |55| utxo.value | value of the output spent by this input |56| utxo.script | locking script of the UTXO |57| utxo.outpoint.txid | txid of the transaction being spent |58| utxo.outpoint.outputIndex | index of the UTXO in the outputs |59| hashPrevouts | If the `ANYONECANPAY` [SIGHASH type](#sighash-type) is not set, it's double SHA256 of the serialization of all input outpoints . Otherwise, it's a `unit256` of `0x0000......0000`. |60| hashSequence | If none of the `ANYONECANPAY`, `SINGLE`, `NONE` [SIGHASH type](#sighash-type) is set, it's double SHA256 of the serialization of sequence of all inputs. Otherwise, it's a `unit256` of `0x0000......0000`. |61| sequence | sequence of the input |62| hashOutputs | If the [SIGHASH type](#sighash-type) is neither `SINGLE` nor `NONE`, it's double SHA256 of the serialization of all outputs. If the [SIGHASH type](#sighash-type) is `SINGLE` and the input index is smaller than the number of outputs, it's the double SHA256 of the output with the same index as the input. Otherwise, it's a `unit256` of `0x0000......0000`. |63| locktime | locktime of the transaction |64| sigHashType| sighash type of the signature |65 66You can directly access the context through `this.ctx` in any public `@method`.67It can be considered additional information a public method gets when called, besides its function parameters.68The example below accesses the [locktime](https://learnmeabitcoin.com/technical/locktime) of the spending transaction.69 70```ts71class CheckLockTimeVerify extends SmartContract {72 @prop()73 readonly matureTime: bigint // Can be timestamp or block height.74 75 constructor(matureTime: bigint) {76 super(...arguments)77 this.matureTime = matureTime78 }79 80 @method()81 public timelock() {82 assert(this.ctx.locktime >= this.matureTime, "locktime too low")83 }84}85```86 87:::note88Accessing `this.ctx` in **non-public** methods is not allowed.89:::90 91```ts92@method()93propagateState(outputs: ByteString) : boolean {94 return this.ctx.hashOutputs == hash256(outputs); // invalid95}96```97 98### Access inputs and outputs99 100The inputs and outpus of the spending transaction are not directly included in `ScriptContext`, but their hashes/digests. To access them, we can build them first and validate they hash to the expected digest, which ensures they are actually from the spending transaction.101The following example ensure both Alice and Bob get 1000 satoshis from the contract.102 103```ts104class DesignatedReceivers extends SmartContract {105 @prop()106 readonly alice: PubKeyHash107 108 @prop()109 readonly bob: PubKeyHash110 111 constructor(alice: PubKeyHash, bob: PubKeyHash) {112 super(...arguments)113 this.alice = alice114 this.bob = bob115 }116 117 @method()118 public payout() {119 const aliceOutput: ByteString = Utils.buildPublicKeyHashOutput(alice, 1000n)120 const bobOutput: ByteString = Utils.buildPublicKeyHashOutput(bob, 1000n)121 let outputs = aliceOutput + bobOutput122 123 // require a change output124 outputs += this.buildChangeOutput();125 126 // ensure outputs are actually from the spending transaction as expected127 assert(this.ctx.hashOutputs == hash256(outputs), 'hashOutputs mismatch')128 }129}130```131 132### SigHash Type133 134[SigHash type](https://wiki.bitcoinsv.io/index.php/SIGHASH_flags) decides which part of the spending transaction is included in `ScriptContext`.135136It defaults to `SigHash.ALL`, including all inputs and outputs. You can customize it by setting the argument of the `@method()` decorator, e.g.,137 138```ts139@method(SigHash.ANYONECANPAY_SINGLE)140public increment() {141 ...142}143```144 145There are a total of 6 sigHash types to choose from:146 147| SigHash Type | Functional Meaning |148| ------------- | ------------- |149| ALL | Sign all inputs and outputs |150| NONE | Sign all inputs and no output |151| SINGLE | Sign all inputs and the output with the same index |152| ANYONECANPAY_ALL | Sign its own input and all outputs |153| ANYONECANPAY_NONE | Sign its own input and no output |154| ANYONECANPAY_SINGLE | Sign its own input and the output with the same index |155 156 157 158 159### Debugging160 161See [How to Debug ScriptContext Failure](../advanced/how-to-debug-scriptcontext.md)162 