@opcat-labs/scrypt-ts-opcat 2.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/.templates/smart-contract/builtin-libs/backtrace.scrypt.map +1 -1
- package/assets/.templates/smart-contract/builtin-libs/backtrace.scrypt.tpl +4 -0
- package/assets/.templates/smart-contract/builtin-libs/genesis.scrypt.map +1 -0
- package/assets/.templates/smart-contract/builtin-libs/genesis.scrypt.tpl +42 -0
- package/assets/.templates/smart-contract/builtin-libs/genesis.transformer.json +9 -0
- package/assets/.templates/smart-contract/builtin-libs/p2pk.scrypt.map +1 -1
- package/assets/.templates/smart-contract/builtin-libs/p2pk.scrypt.tpl +3 -0
- package/assets/.templates/smart-contract/builtin-libs/p2pkh.scrypt.map +1 -1
- package/assets/.templates/smart-contract/builtin-libs/p2pkh.scrypt.tpl +3 -0
- package/assets/smart-contract/builtin-libs/backtrace.scrypt +16 -12
- package/assets/smart-contract/builtin-libs/byteStringReader.scrypt +5 -5
- package/assets/smart-contract/builtin-libs/byteStringWriter.scrypt +6 -6
- package/assets/smart-contract/builtin-libs/contextUtils.scrypt +16 -16
- package/assets/smart-contract/builtin-libs/genesis.scrypt +44 -0
- package/assets/smart-contract/builtin-libs/p2pk.scrypt +4 -1
- package/assets/smart-contract/builtin-libs/p2pkh.scrypt +4 -1
- package/assets/smart-contract/builtin-libs/stateLib.scrypt +1 -1
- package/assets/smart-contract/builtin-libs/stateUtils.scrypt +1 -1
- package/assets/smart-contract/builtin-libs/stdUtils.scrypt +12 -12
- package/assets/smart-contract/builtin-libs/txHashPreimageUtils.scrypt +7 -7
- package/assets/smart-contract/builtin-libs/txUtils.scrypt +12 -12
- package/assets/smart-contract/types/structs.scrypt +8 -8
- package/dist/cjs/features/deployGenesis.cjs +84 -31
- package/dist/cjs/features/deployGenesis.js.map +1 -1
- package/dist/cjs/providers/dryRunProvider.cjs +57 -0
- package/dist/cjs/providers/dryRunProvider.js.map +1 -0
- package/dist/cjs/providers/dummyProvider.cjs +10 -0
- package/dist/cjs/providers/dummyProvider.js.map +1 -1
- package/dist/cjs/providers/index.cjs +4 -1
- package/dist/cjs/providers/index.js.map +1 -1
- package/dist/cjs/providers/mempoolProvider.cjs +44 -0
- package/dist/cjs/providers/mempoolProvider.js.map +1 -1
- package/dist/cjs/providers/rpcProvider.cjs +46 -3
- package/dist/cjs/providers/rpcProvider.js.map +1 -1
- package/dist/cjs/providers/utxoProvider.cjs +9 -1
- package/dist/cjs/providers/utxoProvider.js.map +1 -1
- package/dist/cjs/psbt/extPsbt.cjs +8 -1
- package/dist/cjs/psbt/extPsbt.js.map +1 -1
- package/dist/cjs/psbt/psbt.cjs +3 -1
- package/dist/cjs/psbt/psbt.js.map +1 -1
- package/dist/cjs/smart-contract/builtin-libs/backtrace.cjs +59 -2
- package/dist/cjs/smart-contract/builtin-libs/backtrace.js.map +1 -1
- package/dist/cjs/smart-contract/builtin-libs/genesis.cjs +553 -0
- package/dist/cjs/smart-contract/builtin-libs/genesis.js.map +1 -0
- package/dist/cjs/smart-contract/builtin-libs/index.cjs +5 -1
- package/dist/cjs/smart-contract/builtin-libs/index.js.map +1 -1
- package/dist/cjs/smart-contract/smartContract.cjs +22 -0
- package/dist/cjs/smart-contract/smartContract.js.map +1 -1
- package/dist/esm/features/deployGenesis.js +84 -31
- package/dist/esm/features/deployGenesis.js.map +1 -1
- package/dist/esm/providers/dryRunProvider.js +53 -0
- package/dist/esm/providers/dryRunProvider.js.map +1 -0
- package/dist/esm/providers/dummyProvider.js +10 -0
- package/dist/esm/providers/dummyProvider.js.map +1 -1
- package/dist/esm/providers/index.js +2 -1
- package/dist/esm/providers/index.js.map +1 -1
- package/dist/esm/providers/mempoolProvider.js +44 -0
- package/dist/esm/providers/mempoolProvider.js.map +1 -1
- package/dist/esm/providers/rpcProvider.js +45 -2
- package/dist/esm/providers/rpcProvider.js.map +1 -1
- package/dist/esm/providers/utxoProvider.js +7 -0
- package/dist/esm/providers/utxoProvider.js.map +1 -1
- package/dist/esm/psbt/extPsbt.js +8 -1
- package/dist/esm/psbt/extPsbt.js.map +1 -1
- package/dist/esm/psbt/psbt.js +3 -1
- package/dist/esm/psbt/psbt.js.map +1 -1
- package/dist/esm/smart-contract/builtin-libs/backtrace.js +61 -4
- package/dist/esm/smart-contract/builtin-libs/backtrace.js.map +1 -1
- package/dist/esm/smart-contract/builtin-libs/genesis.js +549 -0
- package/dist/esm/smart-contract/builtin-libs/genesis.js.map +1 -0
- package/dist/esm/smart-contract/builtin-libs/index.js +1 -0
- package/dist/esm/smart-contract/builtin-libs/index.js.map +1 -1
- package/dist/esm/smart-contract/smartContract.js +23 -1
- package/dist/esm/smart-contract/smartContract.js.map +1 -1
- package/dist/types/features/deployGenesis.d.ts +39 -12
- package/dist/types/features/deployGenesis.d.ts.map +1 -1
- package/dist/types/providers/chainProvider.d.ts +12 -0
- package/dist/types/providers/chainProvider.d.ts.map +1 -1
- package/dist/types/providers/dryRunProvider.d.ts +4 -0
- package/dist/types/providers/dryRunProvider.d.ts.map +1 -0
- package/dist/types/providers/dummyProvider.d.ts +4 -2
- package/dist/types/providers/dummyProvider.d.ts.map +1 -1
- package/dist/types/providers/index.d.ts +2 -1
- package/dist/types/providers/index.d.ts.map +1 -1
- package/dist/types/providers/mempoolProvider.d.ts +4 -2
- package/dist/types/providers/mempoolProvider.d.ts.map +1 -1
- package/dist/types/providers/rpcProvider.d.ts +4 -2
- package/dist/types/providers/rpcProvider.d.ts.map +1 -1
- package/dist/types/providers/utxoProvider.d.ts +3 -0
- package/dist/types/providers/utxoProvider.d.ts.map +1 -1
- package/dist/types/psbt/extPsbt.d.ts.map +1 -1
- package/dist/types/psbt/psbt.d.ts.map +1 -1
- package/dist/types/smart-contract/builtin-libs/backtrace.d.ts +49 -0
- package/dist/types/smart-contract/builtin-libs/backtrace.d.ts.map +1 -1
- package/dist/types/smart-contract/builtin-libs/genesis.d.ts +252 -0
- package/dist/types/smart-contract/builtin-libs/genesis.d.ts.map +1 -0
- package/dist/types/smart-contract/builtin-libs/index.d.ts +1 -0
- package/dist/types/smart-contract/builtin-libs/index.d.ts.map +1 -1
- package/dist/types/smart-contract/smartContract.d.ts +20 -0
- package/dist/types/smart-contract/smartContract.d.ts.map +1 -1
- package/package.json +5 -3
- package/scrypt.index.json +4 -0
- package/src/smart-contract/builtin-libs/backtrace.ts +62 -3
- package/src/smart-contract/builtin-libs/genesis.ts +569 -0
- package/src/smart-contract/builtin-libs/index.ts +2 -1
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { SmartContract } from '../smartContract.js';
|
|
2
|
+
import { FixedArray, TxOut } from '../types/index.js';
|
|
3
|
+
import { ContractCall } from '../../psbt/types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Maximum number of inputs allowed during genesis deployment.
|
|
6
|
+
*
|
|
7
|
+
* ## Purpose
|
|
8
|
+
* Limits the number of inputs validated to prevent script size bloat while
|
|
9
|
+
* maintaining sufficient security coverage.
|
|
10
|
+
*
|
|
11
|
+
* ## Why 6?
|
|
12
|
+
* - **Typical deployments**: 1-3 inputs (Genesis UTXO + fee UTXOs)
|
|
13
|
+
* - **Edge case coverage**: Handles multi-input deployment scenarios
|
|
14
|
+
* - **Script size**: Each input check adds ~50 bytes; 6 is optimal balance
|
|
15
|
+
* - **Security**: Validates all inputs in normal cases
|
|
16
|
+
* - **sCrypt constraint**: Bitcoin Script loops must be unrolled at compile time
|
|
17
|
+
*
|
|
18
|
+
* ## Security Implications
|
|
19
|
+
* Transactions with more than 6 inputs will be **rejected by the contract**.
|
|
20
|
+
* This prevents attackers from hiding duplicate scriptHashes in unchecked input
|
|
21
|
+
* indices beyond the validation limit.
|
|
22
|
+
*
|
|
23
|
+
* @constant
|
|
24
|
+
* @see {@link Genesis.checkDeploy} - Uses this constant for input validation
|
|
25
|
+
* @category Genesis
|
|
26
|
+
*/
|
|
27
|
+
export declare const MAX_GENESIS_CHECK_INPUT = 6;
|
|
28
|
+
/**
|
|
29
|
+
* Maximum number of outputs to check during genesis deployment.
|
|
30
|
+
*
|
|
31
|
+
* ## Purpose
|
|
32
|
+
* Limits the number of outputs validated during deployment to match input
|
|
33
|
+
* validation coverage and support typical deployment patterns.
|
|
34
|
+
*
|
|
35
|
+
* ## Usage Scenarios
|
|
36
|
+
* - **1 output**: Deploy single contract
|
|
37
|
+
* - **2-3 outputs**: Deploy contract + change outputs
|
|
38
|
+
* - **4-6 outputs**: Multi-contract deployment or complex output structures
|
|
39
|
+
*
|
|
40
|
+
* ## Validation Scope
|
|
41
|
+
* Only `output[0]` must be unique. Other outputs (1-5) can have duplicate
|
|
42
|
+
* scriptHashes as long as they differ from `output[0]`.
|
|
43
|
+
*
|
|
44
|
+
* @constant
|
|
45
|
+
* @see {@link Genesis.checkDeploy} - Uses this constant for output validation
|
|
46
|
+
* @see {@link MAX_GENESIS_CHECK_INPUT} - Corresponding input limit
|
|
47
|
+
* @category Genesis
|
|
48
|
+
*/
|
|
49
|
+
export declare const MAX_GENESIS_CHECK_OUTPUT = 6;
|
|
50
|
+
/**
|
|
51
|
+
* Genesis contract for validating initial deployment outputs.
|
|
52
|
+
*
|
|
53
|
+
* ## Purpose
|
|
54
|
+
* The Genesis contract ensures that deployed contracts have unique scriptHashes,
|
|
55
|
+
* preventing duplicate deployments and establishing a verifiable deployment origin.
|
|
56
|
+
* It acts as a "genesis UTXO" that validates the first deployment of a contract.
|
|
57
|
+
*
|
|
58
|
+
* ## Deployment Validation Rules
|
|
59
|
+
* 1. **Genesis position**: Genesis must be unlocked at input index 0
|
|
60
|
+
* 2. **Output uniqueness**: Contract at `output[0]` must have unique scriptHash among all outputs
|
|
61
|
+
* 3. **Input differentiation**: Contract at `output[0]` must differ from all input scriptHashes
|
|
62
|
+
* 4. **Input limit**: Transaction must have ≤ {@link MAX_GENESIS_CHECK_INPUT} inputs
|
|
63
|
+
* 5. **Output limit**: Transaction must specify ≤ {@link MAX_GENESIS_CHECK_OUTPUT} outputs
|
|
64
|
+
*
|
|
65
|
+
* ## Why output[0]?
|
|
66
|
+
* Only `output[0]` requires uniqueness validation. This design allows:
|
|
67
|
+
* - Deploying the **primary contract** at output[0] with guaranteed uniqueness
|
|
68
|
+
* - Including **auxiliary contracts** or **change outputs** at indices 1-5
|
|
69
|
+
* - **Multi-output deployments** where only the main contract needs uniqueness
|
|
70
|
+
*
|
|
71
|
+
* ## Empty Placeholders
|
|
72
|
+
* When fewer than {@link MAX_GENESIS_CHECK_OUTPUT} outputs exist, use empty
|
|
73
|
+
* placeholders (scriptHash = empty ByteString) for unused slots. These are
|
|
74
|
+
* ignored during validation.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* **Basic single contract deployment:**
|
|
78
|
+
* ```typescript
|
|
79
|
+
* import { Genesis, genesisCheckDeploy } from '@opcat-labs/scrypt-ts-opcat';
|
|
80
|
+
* import { ExtPsbt } from '@opcat-labs/scrypt-ts-opcat';
|
|
81
|
+
*
|
|
82
|
+
* // 1. Create and bind Genesis contract
|
|
83
|
+
* const genesis = new Genesis();
|
|
84
|
+
* genesis.bindToUtxo(genesisUtxo);
|
|
85
|
+
*
|
|
86
|
+
* // 2. Create the contract to deploy
|
|
87
|
+
* const minter = new CAT20Minter(...);
|
|
88
|
+
*
|
|
89
|
+
* // 3. Build deployment transaction
|
|
90
|
+
* const psbt = new ExtPsbt({ network })
|
|
91
|
+
* .addContractInput(genesis, genesisCheckDeploy()) // Genesis validates deployment
|
|
92
|
+
* .addContractOutput(minter, 1000n) // Deploy at output[0]
|
|
93
|
+
* .change(changeAddress, feeRate)
|
|
94
|
+
* .seal();
|
|
95
|
+
*
|
|
96
|
+
* // 4. Finalize and broadcast
|
|
97
|
+
* await psbt.finalizeAllInputs();
|
|
98
|
+
* const txid = await psbt.broadcast();
|
|
99
|
+
* console.log(`Contract deployed at ${txid}:0`);
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* @category Contract
|
|
103
|
+
* @category Genesis
|
|
104
|
+
* @see {@link genesisCheckDeploy} - Helper function for easier deployment
|
|
105
|
+
* @see {@link MAX_GENESIS_CHECK_INPUT} - Maximum inputs validated
|
|
106
|
+
* @see {@link MAX_GENESIS_CHECK_OUTPUT} - Maximum outputs validated
|
|
107
|
+
* @onchain
|
|
108
|
+
*/
|
|
109
|
+
export declare class Genesis extends SmartContract {
|
|
110
|
+
constructor();
|
|
111
|
+
/**
|
|
112
|
+
* Validates the deployment transaction outputs.
|
|
113
|
+
*
|
|
114
|
+
* ## Validation Process
|
|
115
|
+
* This method performs a **two-phase validation**:
|
|
116
|
+
*
|
|
117
|
+
* **Phase 1: Output Serialization & Uniqueness** (lines 168-183)
|
|
118
|
+
* - Iterates through all outputs up to MAX_GENESIS_CHECK_OUTPUT
|
|
119
|
+
* - Serializes valid outputs (index < outputCount) for context matching
|
|
120
|
+
* - Validates `output[0]` scriptHash is unique among all outputs
|
|
121
|
+
* - Ensures no duplicate contracts are deployed in a single transaction
|
|
122
|
+
*
|
|
123
|
+
* **Phase 2: Input Differentiation** (lines 185-195)
|
|
124
|
+
* - Checks `output[0]` differs from all input scriptHashes
|
|
125
|
+
* - Prevents redeployment attacks using existing contract UTXOs
|
|
126
|
+
* - Validates only inputs within MAX_GENESIS_CHECK_INPUT limit
|
|
127
|
+
*
|
|
128
|
+
* ## Why Two Separate Loops?
|
|
129
|
+
* 1. **Output loop**: Dual-purpose (serialize + validate uniqueness)
|
|
130
|
+
* 2. **Input loop**: Independent validation after outputs are processed
|
|
131
|
+
* 3. **sCrypt constraint**: Loops must be unrolled at compile time
|
|
132
|
+
*
|
|
133
|
+
* @param outputs - Fixed array of 6 outputs; fill unused slots with empty placeholders
|
|
134
|
+
* @param outputCount - Number of actual outputs (1-6); outputs beyond this are ignored
|
|
135
|
+
*
|
|
136
|
+
* @throws {Error} 'Genesis must be unlocked at input index 0' - Genesis not at input 0
|
|
137
|
+
* @throws {Error} 'Too many inputs to validate' - More than MAX_GENESIS_CHECK_INPUT inputs
|
|
138
|
+
* @throws {Error} 'Invalid outputCount' - outputCount out of range [1, 6]
|
|
139
|
+
* @throws {Error} 'Output scriptHash must be non-empty' - Empty scriptHash in valid output
|
|
140
|
+
* @throws {Error} 'output[0] must be unique among all outputs' - Duplicate scriptHash in outputs
|
|
141
|
+
* @throws {Error} 'output[0] must differ from all input scriptHashes' - Matches an input
|
|
142
|
+
* @throws {Error} 'Outputs mismatch with the transaction context' - Serialization mismatch
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```typescript
|
|
146
|
+
* // Advanced: Direct method call (most users should use genesisCheckDeploy helper)
|
|
147
|
+
* const genesis = new Genesis();
|
|
148
|
+
* genesis.bindToUtxo(genesisUtxo);
|
|
149
|
+
*
|
|
150
|
+
* // Create output array with empty placeholders
|
|
151
|
+
* const outputs: TxOut[] = [
|
|
152
|
+
* { scriptHash: sha256(contractScript), satoshis: 1000n, dataHash: sha256('') },
|
|
153
|
+
* ...fill({ scriptHash: toByteString(''), satoshis: 0n, dataHash: sha256('') }, 5)
|
|
154
|
+
* ];
|
|
155
|
+
*
|
|
156
|
+
* await genesis.methods.checkDeploy(
|
|
157
|
+
* outputs as FixedArray<TxOut, 6>,
|
|
158
|
+
* 1n // Only 1 real output, rest are placeholders
|
|
159
|
+
* );
|
|
160
|
+
* ```
|
|
161
|
+
*
|
|
162
|
+
* @see {@link genesisCheckDeploy} - Helper function for easier usage
|
|
163
|
+
* @see {@link MAX_GENESIS_CHECK_INPUT} - Maximum inputs validated
|
|
164
|
+
* @see {@link MAX_GENESIS_CHECK_OUTPUT} - Maximum outputs validated
|
|
165
|
+
* @onchain
|
|
166
|
+
*/
|
|
167
|
+
checkDeploy(outputs: FixedArray<TxOut, typeof MAX_GENESIS_CHECK_OUTPUT>, outputCount: bigint): void;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Creates a contract call function for Genesis.checkDeploy that automatically
|
|
171
|
+
* builds the TxOut array from transaction outputs.
|
|
172
|
+
*
|
|
173
|
+
* ## What it does
|
|
174
|
+
* This helper function simplifies Genesis deployment by:
|
|
175
|
+
* 1. **Extracting outputs** from the PSBT transaction
|
|
176
|
+
* 2. **Computing hashes** (scriptHash and dataHash) for each output
|
|
177
|
+
* 3. **Creating placeholders** for unused output slots (up to 6 total)
|
|
178
|
+
* 4. **Invoking checkDeploy** with properly formatted parameters
|
|
179
|
+
*
|
|
180
|
+
* ## When to use
|
|
181
|
+
* - **Recommended**: Use this helper when building deployment transactions with ExtPsbt
|
|
182
|
+
* - **Advanced**: Call {@link Genesis.checkDeploy} directly for manual control
|
|
183
|
+
*
|
|
184
|
+
* ## Output Handling
|
|
185
|
+
* - Processes up to {@link MAX_GENESIS_CHECK_OUTPUT} (6) outputs
|
|
186
|
+
* - Automatically limits `outputCount` via `Math.min(txOutputs.length, 6)`
|
|
187
|
+
* - Fills unused slots with empty placeholders (scriptHash = empty ByteString)
|
|
188
|
+
*
|
|
189
|
+
* @returns A ContractCall function compatible with ExtPsbt.addContractInput
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* **Basic single contract deployment:**
|
|
193
|
+
* ```typescript
|
|
194
|
+
* import { Genesis, genesisCheckDeploy } from '@opcat-labs/scrypt-ts-opcat';
|
|
195
|
+
* import { ExtPsbt } from '@opcat-labs/scrypt-ts-opcat';
|
|
196
|
+
*
|
|
197
|
+
* // 1. Setup Genesis contract
|
|
198
|
+
* const genesis = new Genesis();
|
|
199
|
+
* genesis.bindToUtxo(genesisUtxo);
|
|
200
|
+
*
|
|
201
|
+
* // 2. Create contract to deploy
|
|
202
|
+
* const minter = new CAT20Minter(...);
|
|
203
|
+
*
|
|
204
|
+
* // 3. Build deployment transaction
|
|
205
|
+
* const psbt = new ExtPsbt({ network })
|
|
206
|
+
* .addContractInput(genesis, genesisCheckDeploy()) // Genesis validates
|
|
207
|
+
* .addContractOutput(minter, 1000n) // Deploy at output[0]
|
|
208
|
+
* .change(changeAddress, feeRate) // Change output
|
|
209
|
+
* .seal();
|
|
210
|
+
*
|
|
211
|
+
* // 4. Finalize and broadcast
|
|
212
|
+
* await psbt.finalizeAllInputs();
|
|
213
|
+
* const txid = await psbt.broadcast();
|
|
214
|
+
* console.log(`Contract deployed at ${txid}:0`);
|
|
215
|
+
* ```
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* **Multi-output deployment:**
|
|
219
|
+
* ```typescript
|
|
220
|
+
* // Deploy primary contract + auxiliary contracts
|
|
221
|
+
* const psbt = new ExtPsbt({ network })
|
|
222
|
+
* .addContractInput(genesis, genesisCheckDeploy())
|
|
223
|
+
* .addContractOutput(primaryContract, 2000n) // output[0] - must be unique
|
|
224
|
+
* .addContractOutput(helperContract, 1000n) // output[1] - can match output[2+]
|
|
225
|
+
* .addContractOutput(anotherHelper, 1000n) // output[2] - can match output[1]
|
|
226
|
+
* .change(changeAddress, feeRate)
|
|
227
|
+
* .seal();
|
|
228
|
+
* ```
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* **Error handling:**
|
|
232
|
+
* ```typescript
|
|
233
|
+
* try {
|
|
234
|
+
* const psbt = new ExtPsbt({ network })
|
|
235
|
+
* .addContractInput(genesis, genesisCheckDeploy())
|
|
236
|
+
* .addContractOutput(contract1, 1000n) // output[0]
|
|
237
|
+
* .addContractOutput(contract1, 1000n) // ❌ Same as output[0] - will fail!
|
|
238
|
+
* .seal();
|
|
239
|
+
* await psbt.finalizeAllInputs();
|
|
240
|
+
* await psbt.broadcast();
|
|
241
|
+
* } catch (error) {
|
|
242
|
+
* // Error: output[0] must be unique among all outputs
|
|
243
|
+
* console.error('Deployment failed:', error.message);
|
|
244
|
+
* }
|
|
245
|
+
* ```
|
|
246
|
+
*
|
|
247
|
+
* @category Genesis
|
|
248
|
+
* @see {@link Genesis.checkDeploy} - The underlying contract method
|
|
249
|
+
* @see {@link MAX_GENESIS_CHECK_OUTPUT} - Maximum outputs validated
|
|
250
|
+
*/
|
|
251
|
+
export declare function genesisCheckDeploy(): ContractCall<Genesis>;
|
|
252
|
+
//# sourceMappingURL=genesis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"genesis.d.ts","sourceRoot":"","sources":["../../../../src/smart-contract/builtin-libs/genesis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAGtD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAEzC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AACH,qBACa,OAAQ,SAAQ,aAAa;;IAMxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuDG;IAEI,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,wBAAwB,CAAC,EAAE,WAAW,EAAE,MAAM;CAyEpG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiFG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CAAC,OAAO,CAAC,CAwC1D"}
|
|
@@ -5,4 +5,5 @@ export { StdUtils } from './stdUtils.js';
|
|
|
5
5
|
export { Backtrace, type ChainTxVerifyResponse } from './backtrace.js';
|
|
6
6
|
export { StateLib } from './stateLib.js';
|
|
7
7
|
export { TxHashPreimageUtils } from './txHashPreimageUtils.js';
|
|
8
|
+
export { Genesis, MAX_GENESIS_CHECK_OUTPUT, genesisCheckDeploy } from './genesis.js';
|
|
8
9
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/smart-contract/builtin-libs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,KAAK,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/smart-contract/builtin-libs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,KAAK,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -43,12 +43,32 @@ export declare class SmartContract<StateT extends OpcatState = undefined> extend
|
|
|
43
43
|
* @ignore
|
|
44
44
|
*/
|
|
45
45
|
getStateType(): string | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* Get the data of the contract.
|
|
48
|
+
* @returns the data of the contract
|
|
49
|
+
*/
|
|
50
|
+
get data(): ByteString;
|
|
51
|
+
/**
|
|
52
|
+
* Set the data of the contract.
|
|
53
|
+
* Only stateless contracts (without stateType) can set data.
|
|
54
|
+
* Stateful contracts should use the state property instead.
|
|
55
|
+
* @param value the data to set
|
|
56
|
+
*/
|
|
57
|
+
set data(value: ByteString);
|
|
46
58
|
utxo?: ExtUtxo;
|
|
47
59
|
/**
|
|
48
60
|
* The state of the contract UTXO, usually committed to the first OP_RETURN output, is revealed when spending.
|
|
49
61
|
* @onchain
|
|
50
62
|
*/
|
|
51
63
|
state: StateT;
|
|
64
|
+
/**
|
|
65
|
+
* Raw data for stateless contracts (contracts without stateType).
|
|
66
|
+
* For stateful contracts, use the `state` property instead.
|
|
67
|
+
* Access this field through the `data` getter/setter.
|
|
68
|
+
* @private
|
|
69
|
+
* @onchain
|
|
70
|
+
*/
|
|
71
|
+
private _data;
|
|
52
72
|
private contractHeader;
|
|
53
73
|
/**
|
|
54
74
|
* Locking script corresponding to the SmartContract
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smartContract.d.ts","sourceRoot":"","sources":["../../../src/smart-contract/smartContract.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAK/C,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvE,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAc,QAAQ,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAExE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EACL,KAAK,EACL,WAAW,EACX,UAAU,EACV,kBAAkB,EACnB,MAAM,uBAAuB,CAAC;AAK/B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAOnD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C;;GAEG;AACH,UAAU,cAAc;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,kBAAkB,EAAE,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,aAAa,CAAC,MAAM,SAAS,UAAU,GAAG,SAAS,CAC9D,SAAQ,gBAAgB;IACxB;;OAEG;IACH,OAAc,QAAQ,EAAE,QAAQ,CAAC;IACjC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAkB;IAC9C,gBAAuB,IAAI,EAAE,MAAM,EAAE,CAAM;IAE3C;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAE1B;;;OAGG;IACH,YAAY,IAAI,MAAM,GAAG,SAAS;IAKlC,IAAI,CAAC,EAAE,OAAO,CAAC;IAEf;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"smartContract.d.ts","sourceRoot":"","sources":["../../../src/smart-contract/smartContract.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opcat-labs/scrypt-ts-opcat",
|
|
3
3
|
"description": "A TypeScript library for building OPCAT smart contracts with sCrypt.",
|
|
4
|
-
"version": "2.0
|
|
4
|
+
"version": "2.1.0",
|
|
5
5
|
"author": "OP_CAT Labs",
|
|
6
6
|
"main": "./dist/cjs/index.cjs",
|
|
7
7
|
"module": "./dist/esm/index.js",
|
|
@@ -31,8 +31,9 @@
|
|
|
31
31
|
"node": ">=20.0.0"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
|
-
"test": "npm run test:local",
|
|
34
|
+
"test": "npm run test:local && npm run test:dist",
|
|
35
35
|
"test:local": "cross-env DUMMY_PROVIDER=1 mocha",
|
|
36
|
+
"test:dist": "node test-esm/test.mjs && node test-cjs/test.cjs",
|
|
36
37
|
"test:testnet": "cross-env NETWORK=opcat-testnet mocha --timeout=0 --jobs=1",
|
|
37
38
|
"test:mainnet": "cross-env NETWORK=opcat-mainnet mocha --timeout=0 --jobs=1",
|
|
38
39
|
"build:cjs": "tsc -p tsconfig.cjs.json",
|
|
@@ -40,6 +41,7 @@
|
|
|
40
41
|
"build:esm": "tsc -p tsconfig.esm.json",
|
|
41
42
|
"build": "yarn run build:cjs && yarn run build:esm",
|
|
42
43
|
"gen:assets": "tspc -p tsconfig.assets.json && node injectAsm.cjs",
|
|
44
|
+
"gen:contract": "tsx scripts/genContract.ts",
|
|
43
45
|
"prebuild": "yarn run clean",
|
|
44
46
|
"beta": "yarn publish --tag beta --access public",
|
|
45
47
|
"genkey": "tsx test/utils/privateKey.ts",
|
|
@@ -66,7 +68,7 @@
|
|
|
66
68
|
},
|
|
67
69
|
"dependencies": {
|
|
68
70
|
"@noble/curves": "^1.8.1",
|
|
69
|
-
"@opcat-labs/opcat": "2.0
|
|
71
|
+
"@opcat-labs/opcat": "2.1.0",
|
|
70
72
|
"bip174": "^3.0.0-rc.1",
|
|
71
73
|
"cbor2": "^2.0.1",
|
|
72
74
|
"cross-fetch": "^4.1.0",
|
package/scrypt.index.json
CHANGED
|
@@ -69,6 +69,10 @@
|
|
|
69
69
|
"symbol": "StateLib",
|
|
70
70
|
"path": "smart-contract/builtin-libs/stateLib.scrypt.tpl"
|
|
71
71
|
},
|
|
72
|
+
{
|
|
73
|
+
"symbol": "Genesis",
|
|
74
|
+
"path": "smart-contract/builtin-libs/genesis.scrypt.tpl"
|
|
75
|
+
},
|
|
72
76
|
{
|
|
73
77
|
"symbol": "P2PK",
|
|
74
78
|
"path": "smart-contract/builtin-libs/p2pk.scrypt.tpl"
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { method } from '../decorators.js';
|
|
1
|
+
import { method, prop } from '../decorators.js';
|
|
2
2
|
import { assert } from '../fns/assert.js';
|
|
3
3
|
import { SmartContractLib } from '../smartContractLib.js';
|
|
4
4
|
import { ByteString } from '../types/index.js';
|
|
5
5
|
import { BacktraceInfo, Prevouts, TxHashPreimage } from '../types/structs.js';
|
|
6
6
|
import { TxUtils } from './txUtils.js';
|
|
7
7
|
import { TX_INPUT_BYTE_LEN, TX_OUTPUT_BYTE_LEN, TX_OUTPUT_SATOSHI_BYTE_LEN, TX_OUTPUT_SCRIPT_HASH_LEN } from '../consts.js';
|
|
8
|
-
import { slice } from '../fns/byteString.js';
|
|
8
|
+
import { slice, toByteString } from '../fns/byteString.js';
|
|
9
9
|
import { StdUtils } from './stdUtils.js';
|
|
10
10
|
import { TxHashPreimageUtils } from './txHashPreimageUtils.js';
|
|
11
11
|
|
|
@@ -25,6 +25,25 @@ export type ChainTxVerifyResponse = {
|
|
|
25
25
|
* @onchain
|
|
26
26
|
*/
|
|
27
27
|
export class Backtrace extends SmartContractLib {
|
|
28
|
+
/**
|
|
29
|
+
* SHA256 hash of the Genesis contract script (including header).
|
|
30
|
+
* Used to validate that prevPrevScript is the Genesis contract when tracing back to genesis outpoint.
|
|
31
|
+
*
|
|
32
|
+
* ## How this hash is generated
|
|
33
|
+
* This is the SHA256 hash of the Genesis contract's full locking script, including:
|
|
34
|
+
* - Contract header (name, version metadata)
|
|
35
|
+
* - Compiled bytecode
|
|
36
|
+
*
|
|
37
|
+
* To verify or regenerate: `sha256(toByteString(new Genesis().lockingScript.toHex()))`
|
|
38
|
+
*
|
|
39
|
+
* ## Important
|
|
40
|
+
* If the Genesis contract is updated, this hash MUST be updated accordingly.
|
|
41
|
+
* Use the test in genesis.test.ts to verify this hash remains correct.
|
|
42
|
+
*
|
|
43
|
+
* @see packages/scrypt-ts-opcat/test/local-test/genesis.test.ts - GENESIS_SCRIPT_HASH validation tests
|
|
44
|
+
*/
|
|
45
|
+
@prop()
|
|
46
|
+
static readonly GENESIS_SCRIPT_HASH: ByteString = toByteString('8f6157664f8f7cd43e6bba7f3209bb803d4d0fb2fb6e59fdc548989ed3901f15');
|
|
28
47
|
|
|
29
48
|
/**
|
|
30
49
|
* Verifies that the transaction hash preimage matches the previous transaction hash
|
|
@@ -47,6 +66,37 @@ export class Backtrace extends SmartContractLib {
|
|
|
47
66
|
/**
|
|
48
67
|
* Back-to-genesis backtrace verification for a contract which can be backtraced to the genesis outpoint.
|
|
49
68
|
* It will be a valid backtraceInfo if the prevPrevOutpoint is the genesis outpoint or the prevPrevScript is the selfScript.
|
|
69
|
+
*
|
|
70
|
+
* ## Multiple Genesis Support
|
|
71
|
+
* A single transaction can create multiple Genesis outputs at different indices (output[0], output[1], etc.).
|
|
72
|
+
* Each Genesis output can be spent separately to deploy a different contract, with each contract having
|
|
73
|
+
* its own unique genesisOutpoint. This allows batch creation of Genesis contracts in one transaction
|
|
74
|
+
* while maintaining independent contract lineages.
|
|
75
|
+
*
|
|
76
|
+
* ```
|
|
77
|
+
* Genesis Creation Tx
|
|
78
|
+
* +-------------------+
|
|
79
|
+
* | output[0] |---> Genesis_0 (outpoint: txid:0)
|
|
80
|
+
* UTXOs -------------->| output[1] |---> Genesis_1 (outpoint: txid:1)
|
|
81
|
+
* | output[2] |---> Genesis_2 (outpoint: txid:2)
|
|
82
|
+
* +-------------------+
|
|
83
|
+
* |
|
|
84
|
+
* +----------------------+----------------------+
|
|
85
|
+
* | | |
|
|
86
|
+
* v v v
|
|
87
|
+
* +-------------+ +-------------+ +-------------+
|
|
88
|
+
* | Deploy Tx A | | Deploy Tx B | | Deploy Tx C |
|
|
89
|
+
* +-------------+ +-------------+ +-------------+
|
|
90
|
+
* | spend Gen_0 | | spend Gen_1 | | spend Gen_2 |
|
|
91
|
+
* | output[0]: | | output[0]: | | output[0]: |
|
|
92
|
+
* | Contract_A | | Contract_B | | Contract_C |
|
|
93
|
+
* +-------------+ +-------------+ +-------------+
|
|
94
|
+
* | | |
|
|
95
|
+
* v v v
|
|
96
|
+
* genesisOutpoint: genesisOutpoint: genesisOutpoint:
|
|
97
|
+
* txid:0 txid:1 txid:2
|
|
98
|
+
* ```
|
|
99
|
+
*
|
|
50
100
|
* @param backtraceInfo backtrace info to verify, including prevTx and prevPrevTx informations
|
|
51
101
|
* @param t_genesisOutpoint expected genesis outpoint of the contract which usually is a contract property and trustable
|
|
52
102
|
* @param t_selfScript expected self locking script, i.e. this.ctx.spentScript, of the currect spending UTXO context which is trustable
|
|
@@ -60,6 +110,13 @@ export class Backtrace extends SmartContractLib {
|
|
|
60
110
|
t_prevTxInputList: ByteString,
|
|
61
111
|
): void {
|
|
62
112
|
const res = Backtrace.verifyChainTxs(backtraceInfo, t_prevTxInputList);
|
|
113
|
+
// When at genesis outpoint, verify the prevPrevScript (scriptHash) matches the Genesis contract
|
|
114
|
+
if (res.prevPrevOutpoint === t_genesisOutpoint) {
|
|
115
|
+
assert(
|
|
116
|
+
res.prevPrevScript == Backtrace.GENESIS_SCRIPT_HASH,
|
|
117
|
+
`prevPrevScript does not match Genesis contract script`,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
63
120
|
assert(
|
|
64
121
|
res.prevPrevOutpoint === t_genesisOutpoint || res.prevPrevScript == t_selfScript,
|
|
65
122
|
`can not backtrace to the genesis outpoint`,
|
|
@@ -104,17 +161,19 @@ export class Backtrace extends SmartContractLib {
|
|
|
104
161
|
// check if the passed prevTxInput and prevTxInputIndexVal are matched
|
|
105
162
|
assert(
|
|
106
163
|
slice(
|
|
107
|
-
t_prevTxInputList,
|
|
164
|
+
t_prevTxInputList,
|
|
108
165
|
backtraceInfo.prevTxInputIndex * TX_INPUT_BYTE_LEN,
|
|
109
166
|
(backtraceInfo.prevTxInputIndex + 1n) * TX_INPUT_BYTE_LEN
|
|
110
167
|
) ==
|
|
111
168
|
TxUtils.mergeInput(backtraceInfo.prevTxInput),
|
|
169
|
+
'prevTxInput does not match prevTxInputList at specified index',
|
|
112
170
|
);
|
|
113
171
|
// check if prevTxHash of passed prevTxInput and prevPrevTx are matched
|
|
114
172
|
const prevPrevTxHash = backtraceInfo.prevTxInput.prevTxHash;
|
|
115
173
|
assert(
|
|
116
174
|
prevPrevTxHash ==
|
|
117
175
|
TxHashPreimageUtils.getTxHashFromTxHashPreimage(backtraceInfo.prevPrevTxPreimage),
|
|
176
|
+
'prevPrevTxHash mismatch: prevTxInput.prevTxHash does not match prevPrevTxPreimage hash',
|
|
118
177
|
);
|
|
119
178
|
// all fields in backtraceInfo have been verified
|
|
120
179
|
const prevPrevScript =
|