Skip to content

Commit 81602c3

Browse files
committed
Add more multicontract debugging tests and slight updates to SiblingIntrospection.cash
1 parent 607cfb5 commit 81602c3

File tree

5 files changed

+74
-33
lines changed

5 files changed

+74
-33
lines changed

packages/cashscript/test/e2e/MultiContract.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,8 @@ describe('Multi Contract', () => {
252252

253253
// then
254254
await expect(txPromise).rejects.toThrow(FailedRequireError);
255-
await expect(txPromise).rejects.toThrow('SiblingIntrospection.cash:7 Require statement failed at input 0 in contract SiblingIntrospection.cash at line 7 with the following message: input bytecode should match.');
256-
await expect(txPromise).rejects.toThrow('Failing statement: require(inputBytecode == expectedLockingBytecode, \'input bytecode should match\')');
255+
await expect(txPromise).rejects.toThrow('SiblingIntrospection.cash:7 Require statement failed at input 0 in contract SiblingIntrospection.cash at line 7 with the following message: output bytecode should match.');
256+
await expect(txPromise).rejects.toThrow('Failing statement: require(outputBytecode == expectedLockingBytecode, \'output bytecode should match\')');
257257
});
258258
});
259259
});

packages/cashscript/test/fixture/SiblingIntrospection.artifact.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@ export default {
1212
inputs: [],
1313
},
1414
],
15-
bytecode: 'OP_INPUTINDEX OP_0 OP_NUMEQUALVERIFY OP_1 OP_UTXOBYTECODE OP_OVER OP_EQUALVERIFY OP_1 OP_OUTPUTBYTECODE OP_EQUAL',
16-
source: 'contract SiblingIntrospection(bytes expectedLockingBytecode) {\n function spend() {\n require(this.activeInputIndex == 0);\n\n bytes inputBytecode = tx.inputs[1].lockingBytecode;\n console.log("inputBytecode:", inputBytecode);\n require(inputBytecode == expectedLockingBytecode, \'input bytecode should match\');\n\n bytes outputBytecode = tx.outputs[1].lockingBytecode;\n console.log("outputBytecode:", outputBytecode);\n require(outputBytecode == expectedLockingBytecode, \'output bytecode should match\');\n }\n}\n',
15+
bytecode: 'OP_INPUTINDEX OP_0 OP_NUMEQUALVERIFY OP_1 OP_OUTPUTBYTECODE OP_OVER OP_EQUALVERIFY OP_1 OP_UTXOBYTECODE OP_EQUAL',
16+
source: 'contract SiblingIntrospection(bytes expectedLockingBytecode) {\n function spend() {\n require(this.activeInputIndex == 0);\n\n bytes outputBytecode = tx.outputs[1].lockingBytecode;\n console.log("outputBytecode:", outputBytecode);\n require(outputBytecode == expectedLockingBytecode, \'output bytecode should match\');\n\n bytes inputBytecode = tx.inputs[1].lockingBytecode;\n console.log("inputBytecode:", inputBytecode);\n require(inputBytecode == expectedLockingBytecode, \'input bytecode should match\');\n }\n}\n',
1717
debug: {
18-
bytecode: 'c0009d51c7788851cd87',
19-
sourceMap: '3:16:3:37;:41::42;:8::44:1;5:40:5:41:0;:30::58:1;7:33:7:56:0;:8::89:1;9:42:9:43:0;:31::60:1;11:8:11:91',
18+
bytecode: 'c0009d51cd788851c787',
19+
sourceMap: '3:16:3:37;:41::42;:8::44:1;5:42:5:43:0;:31::60:1;7:34:7:57:0;:8::91:1;9:40:9:41:0;:30::58:1;11:8:11:89',
2020
logs: [
2121
{
2222
ip: 6,
2323
line: 6,
2424
data: [
25-
'inputBytecode:',
25+
'outputBytecode:',
2626
{
2727
stackIndex: 0,
2828
type: 'bytes',
@@ -34,7 +34,7 @@ export default {
3434
ip: 10,
3535
line: 10,
3636
data: [
37-
'outputBytecode:',
37+
'inputBytecode:',
3838
{
3939
stackIndex: 0,
4040
type: 'bytes',
@@ -51,18 +51,18 @@ export default {
5151
{
5252
ip: 7,
5353
line: 7,
54-
message: 'input bytecode should match',
54+
message: 'output bytecode should match',
5555
},
5656
{
5757
ip: 11,
5858
line: 11,
59-
message: 'output bytecode should match',
59+
message: 'input bytecode should match',
6060
},
6161
],
6262
},
6363
compiler: {
6464
name: 'cashc',
6565
version: '0.11.0-next.4',
6666
},
67-
updatedAt: '2025-06-16T15:05:53.699Z',
67+
updatedAt: '2025-06-16T16:07:30.092Z',
6868
} as const;

packages/cashscript/test/fixture/SiblingIntrospection.cash

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ contract SiblingIntrospection(bytes expectedLockingBytecode) {
22
function spend() {
33
require(this.activeInputIndex == 0);
44

5-
bytes inputBytecode = tx.inputs[1].lockingBytecode;
6-
console.log("inputBytecode:", inputBytecode);
7-
require(inputBytecode == expectedLockingBytecode, 'input bytecode should match');
8-
95
bytes outputBytecode = tx.outputs[1].lockingBytecode;
106
console.log("outputBytecode:", outputBytecode);
117
require(outputBytecode == expectedLockingBytecode, 'output bytecode should match');
8+
9+
bytes inputBytecode = tx.inputs[1].lockingBytecode;
10+
console.log("inputBytecode:", inputBytecode);
11+
require(inputBytecode == expectedLockingBytecode, 'input bytecode should match');
1212
}
1313
}

packages/cashscript/test/fixture/SiblingIntrospection.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,17 @@
1212
"inputs": []
1313
}
1414
],
15-
"bytecode": "OP_INPUTINDEX OP_0 OP_NUMEQUALVERIFY OP_1 OP_UTXOBYTECODE OP_OVER OP_EQUALVERIFY OP_1 OP_OUTPUTBYTECODE OP_EQUAL",
16-
"source": "contract SiblingIntrospection(bytes expectedLockingBytecode) {\n function spend() {\n require(this.activeInputIndex == 0);\n\n bytes inputBytecode = tx.inputs[1].lockingBytecode;\n console.log(\"inputBytecode:\", inputBytecode);\n require(inputBytecode == expectedLockingBytecode, 'input bytecode should match');\n\n bytes outputBytecode = tx.outputs[1].lockingBytecode;\n console.log(\"outputBytecode:\", outputBytecode);\n require(outputBytecode == expectedLockingBytecode, 'output bytecode should match');\n }\n}\n",
15+
"bytecode": "OP_INPUTINDEX OP_0 OP_NUMEQUALVERIFY OP_1 OP_OUTPUTBYTECODE OP_OVER OP_EQUALVERIFY OP_1 OP_UTXOBYTECODE OP_EQUAL",
16+
"source": "contract SiblingIntrospection(bytes expectedLockingBytecode) {\n function spend() {\n require(this.activeInputIndex == 0);\n\n bytes outputBytecode = tx.outputs[1].lockingBytecode;\n console.log(\"outputBytecode:\", outputBytecode);\n require(outputBytecode == expectedLockingBytecode, 'output bytecode should match');\n\n bytes inputBytecode = tx.inputs[1].lockingBytecode;\n console.log(\"inputBytecode:\", inputBytecode);\n require(inputBytecode == expectedLockingBytecode, 'input bytecode should match');\n }\n}\n",
1717
"debug": {
18-
"bytecode": "c0009d51c7788851cd87",
19-
"sourceMap": "3:16:3:37;:41::42;:8::44:1;5:40:5:41:0;:30::58:1;7:33:7:56:0;:8::89:1;9:42:9:43:0;:31::60:1;11:8:11:91",
18+
"bytecode": "c0009d51cd788851c787",
19+
"sourceMap": "3:16:3:37;:41::42;:8::44:1;5:42:5:43:0;:31::60:1;7:34:7:57:0;:8::91:1;9:40:9:41:0;:30::58:1;11:8:11:89",
2020
"logs": [
2121
{
2222
"ip": 6,
2323
"line": 6,
2424
"data": [
25-
"inputBytecode:",
25+
"outputBytecode:",
2626
{
2727
"stackIndex": 0,
2828
"type": "bytes",
@@ -34,7 +34,7 @@
3434
"ip": 10,
3535
"line": 10,
3636
"data": [
37-
"outputBytecode:",
37+
"inputBytecode:",
3838
{
3939
"stackIndex": 0,
4040
"type": "bytes",
@@ -51,18 +51,18 @@
5151
{
5252
"ip": 7,
5353
"line": 7,
54-
"message": "input bytecode should match"
54+
"message": "output bytecode should match"
5555
},
5656
{
5757
"ip": 11,
5858
"line": 11,
59-
"message": "output bytecode should match"
59+
"message": "input bytecode should match"
6060
}
6161
]
6262
},
6363
"compiler": {
6464
"name": "cashc",
6565
"version": "0.11.0-next.4"
6666
},
67-
"updatedAt": "2025-06-16T15:05:53.452Z"
67+
"updatedAt": "2025-06-16T16:07:29.693Z"
6868
}

packages/cashscript/test/multi-contract-debugging.test.ts

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,52 @@ const provider = new MockNetworkProvider();
2727

2828
describe('Multi-Contract-Debugging tests', () => {
2929
describe('console.log statements', () => {
30-
it.todo('should log all executed console.log statements across all contracts');
31-
it.todo('should not log statements that are not executed');
32-
it.todo('should log console.log statements in the correct order (by input index)');
33-
it.todo('should be able to log correct input bytecode for other contracts');
34-
it.todo('should be able to log correct output bytecode for other contracts');
30+
describe('Sibling introspection', () => {
31+
const sameNameDifferentPathContract = new Contract(ARTIFACT_SAME_NAME_DIFFERENT_PATH, [0n], { provider });
32+
33+
const expectedLockingBytecode = addressToLockScript(sameNameDifferentPathContract.address);
34+
const siblingIntrospectionContract = new Contract(
35+
SiblingIntrospectionArtifact,
36+
[expectedLockingBytecode],
37+
{ provider },
38+
);
39+
40+
const sameNameDifferentPathContractUtxo = randomUtxo();
41+
const siblingIntrospectionUtxo = randomUtxo();
42+
43+
(provider as any).addUtxo?.(sameNameDifferentPathContract.address, sameNameDifferentPathContractUtxo);
44+
(provider as any).addUtxo?.(siblingIntrospectionContract.address, siblingIntrospectionUtxo);
45+
46+
it('should log correct data in all executed console.log statements across all contracts in the correct order by input index', () => {
47+
const tx = new TransactionBuilder({ provider })
48+
.addInput(siblingIntrospectionUtxo, siblingIntrospectionContract.unlock.spend())
49+
.addInput(sameNameDifferentPathContractUtxo, sameNameDifferentPathContract.unlock.function_1(0n))
50+
.addOutput({ to: siblingIntrospectionContract.address, amount: siblingIntrospectionUtxo.satoshis })
51+
.addOutput({
52+
to: sameNameDifferentPathContract.address,
53+
amount: sameNameDifferentPathContractUtxo.satoshis - 2000n,
54+
});
55+
56+
expect(tx).toLog('SiblingIntrospection.cash:6 outputBytecode: 0xaa2092e16594dd458916b3aa6cae4bf41352d1b3b39658698e8cddbeedd687efec7587\nSiblingIntrospection.cash:10 inputBytecode: 0xaa2092e16594dd458916b3aa6cae4bf41352d1b3b39658698e8cddbeedd687efec7587\nSameNameDifferentPath.cash:5 a is 0');
57+
});
58+
59+
it('should log correct data for the reached console.log statements if a require statement fails, and not log unreached console.log statements', () => {
60+
const tx = new TransactionBuilder({ provider })
61+
.addInput(siblingIntrospectionUtxo, siblingIntrospectionContract.unlock.spend())
62+
.addInput(sameNameDifferentPathContractUtxo, sameNameDifferentPathContract.unlock.function_1(1n))
63+
.addOutput({ to: siblingIntrospectionContract.address, amount: siblingIntrospectionUtxo.satoshis })
64+
.addOutput({
65+
to: siblingIntrospectionContract.address,
66+
amount: sameNameDifferentPathContractUtxo.satoshis - 2000n,
67+
});
68+
69+
expect(tx).toLog('SiblingIntrospection.cash:6 outputBytecode: 0xaa20d510df1721debb0d678d8e424b5f64f04f820005f017cb4731f7be94cd63755787');
70+
expect(tx).not.toLog('SiblingIntrospection.cash:10 inputBytecode: 0xaa2092e16594dd458916b3aa6cae4bf41352d1b3b39658698e8cddbeedd687efec7587');
71+
expect(tx).not.toLog('SameNameDifferentPath.cash:5 a is 0');
72+
});
73+
});
74+
75+
it.todo('should not log statements that are not executed'); // Maybe this is already included in tests above
3576
it.todo('should still work with different instances of the same contract, with different paths due to different contract parameter values');
3677
});
3778

@@ -209,7 +250,7 @@ describe('Multi-Contract-Debugging tests', () => {
209250
.addOutput({ to: siblingIntrospectionContract.address, amount: siblingIntrospectionUtxo.satoshis })
210251
.addOutput({ to: correctContract.address, amount: incorrectContractUtxo.satoshis - 2000n });
211252

212-
expect(tx).toFailRequireWith('SiblingIntrospection.cash:7 Require statement failed at input 0 in contract SiblingIntrospection.cash at line 7 with the following message: input bytecode should match.');
253+
expect(tx).toFailRequireWith('SiblingIntrospection.cash:11 Require statement failed at input 0 in contract SiblingIntrospection.cash at line 11 with the following message: input bytecode should match.');
213254
expect(tx).toFailRequireWith('Failing statement: require(inputBytecode == expectedLockingBytecode, \'input bytecode should match\')');
214255
});
215256

@@ -220,7 +261,7 @@ describe('Multi-Contract-Debugging tests', () => {
220261
.addOutput({ to: siblingIntrospectionContract.address, amount: siblingIntrospectionUtxo.satoshis })
221262
.addOutput({ to: incorrectContract.address, amount: correctContractUtxo.satoshis - 2000n });
222263

223-
expect(tx).toFailRequireWith('SiblingIntrospection.cash:11 Require statement failed at input 0 in contract SiblingIntrospection.cash at line 11 with the following message: output bytecode should match.');
264+
expect(tx).toFailRequireWith('SiblingIntrospection.cash:7 Require statement failed at input 0 in contract SiblingIntrospection.cash at line 7 with the following message: output bytecode should match.');
224265
expect(tx).toFailRequireWith('Failing statement: require(outputBytecode == expectedLockingBytecode, \'output bytecode should match\')');
225266
});
226267
});
@@ -267,14 +308,14 @@ describe('Multi-Contract-Debugging tests', () => {
267308
.addInput(contract2Utxo, p2pkhContract2.unlock.function_1(0n))
268309
.addOutput({ to: p2pkhContract1.address, amount: 10000n });
269310

270-
expect(transaction1).toFailRequireWith('SameNameDifferentPath.cash:7 Require statement failed at input 1 in contract SameNameDifferentPath.cash at line 7 with the following message: b should not be 0.');
311+
expect(transaction1).toFailRequireWith('SameNameDifferentPath.cash:9 Require statement failed at input 1 in contract SameNameDifferentPath.cash at line 9 with the following message: b should not be 0.');
271312

272313
const transaction2 = new TransactionBuilder({ provider })
273314
.addInput(contract1Utxo, p2pkhContract1.unlock.function_1(1n))
274315
.addInput(contract2Utxo, p2pkhContract2.unlock.function_1(1n))
275316
.addOutput({ to: p2pkhContract1.address, amount: 10000n });
276317

277-
expect(transaction2).toFailRequireWith('SameNameDifferentPath.cash:5 Require statement failed at input 0 in contract SameNameDifferentPath.cash at line 5 with the following message: b should be 0.');
318+
expect(transaction2).toFailRequireWith('SameNameDifferentPath.cash:6 Require statement failed at input 0 in contract SameNameDifferentPath.cash at line 6 with the following message: b should be 0.');
278319
});
279320
});
280321

0 commit comments

Comments
 (0)