Skip to content

Commit 4aebc14

Browse files
committed
Add libs
Add libs parsing if code is exotic. Via dton.io... Ironic. And dton has broken testnet.
1 parent 718f7fa commit 4aebc14

File tree

3 files changed

+81
-30
lines changed

3 files changed

+81
-30
lines changed

src/runner/runner.spec.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { getEmulationWithStack, waitForRateLimit } from './runner';
33
import { AccountFromAPI } from './types';
44
import { linkToTx, mcSeqnoByShard, txToLinks } from './utils';
55

6-
describe('Converter', () => {
6+
describe.skip('Converter', () => {
77
const justHash =
88
'3e5f49798de239da5d8f80b4dc300204d37613e4203a3f7b877c04a88c81856b';
99
const toncx =
@@ -90,6 +90,8 @@ describe('Converter', () => {
9090
});
9191

9292
describe('Runner', () => {
93+
const withLibs =
94+
'https://ton.cx/tx/47769590000001:TfGC2E6eG7522c/jW9AjwkTFWwPL0RhFd2mGiqLoW/Q=:EQC39c119oqPkaB-fiA8_EKfejP24_IyKCNEyKFUsvXsfIHe';
9395
const first =
9496
'https://ton.cx/tx/44640875000007:53bLbTDYoHiBHGJPz2/oGr1JvJ/SS7iVVeMTUi5PYpw=:EQCtJGu1Q5xptmRFuP16M2w01QValw3V8IiyxQczAf83YITE';
9597
const txs = [
@@ -109,8 +111,11 @@ describe('Runner', () => {
109111
'https://ton.cx/tx/46843694000021:nwjPEIK88JGyPRLFVzNYHKkBb62OyVSgZKuU6J0mLC0=:EQA--JhKKuYfb-WAw7vDWEfD4fg2WOt9AuLH6xHPvF0RTUNA',
110112
];
111113

112-
// it('should emulate with libs', async () => {
113-
// });
114+
it('should emulate with libs', async () => {
115+
await waitForRateLimit();
116+
const res = await getEmulationWithStack(withLibs, false);
117+
expect(res.stateUpdateHashOk).toBe(true);
118+
});
114119

115120
it('should emulate first tx', async () => {
116121
await waitForRateLimit();

src/runner/runner.ts

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
loadShardAccount,
1414
Transaction,
1515
loadTransaction,
16+
Dictionary,
1617
} from '@ton/core';
1718
import {
1819
loadConfigParamsAsSlice,
@@ -29,7 +30,7 @@ import {
2930
TVMLog,
3031
} from './types';
3132
import { parseStack } from './stack';
32-
import { linkToTx, mcSeqnoByShard, txToLinks } from './utils';
33+
import { getLib, linkToTx, mcSeqnoByShard, txToLinks } from './utils';
3334

3435
function b64ToBigInt(b64: string): bigint {
3536
return BigInt('0x' + Buffer.from(b64, 'base64').toString('hex'));
@@ -213,13 +214,37 @@ export async function getEmulationWithStack(
213214
account = getAccountResult.account;
214215
let initialShardAccount = createShardAccountFromAPI(account, address);
215216

216-
// 4.1 get account stete after all txs for (maybe) verification
217-
const { account: accountAfter } = await clientV4.getAccount(
218-
mcBlockSeqno,
219-
address
217+
const state = initialShardAccount.account?.storage.state;
218+
219+
// 4.1 Get libs if needed
220+
const _libs = Dictionary.empty(
221+
Dictionary.Keys.BigUint(256),
222+
Dictionary.Values.Cell()
220223
);
221-
console.log(account.balance.coins, 'coins before');
222-
if (isOurTxLastTx) console.log(accountAfter.balance.coins, 'coins after');
224+
if (state?.type == 'active') {
225+
sendStatus('Getting libs');
226+
const code = state.state.code;
227+
if (code instanceof Cell && code.bits.length == 256 + 8) {
228+
const cs = code.beginParse(true);
229+
const tag = cs.loadUint(8);
230+
if (tag == 2) {
231+
const libHash = cs.loadBuffer(32);
232+
const libHashHex = libHash.toString('hex').toUpperCase();
233+
const actualCode = await getLib(libHashHex, testnet);
234+
_libs.set(BigInt(`0x${libHashHex}`), actualCode);
235+
}
236+
}
237+
}
238+
let libs: Cell | null = null;
239+
if (_libs.size > 0) libs = beginCell().storeDictDirect(_libs).endCell();
240+
241+
// 4.2 get account state after all txs for (maybe) verification
242+
// const { account: accountAfter } = await clientV4.getAccount(
243+
// mcBlockSeqno,
244+
// address
245+
// );
246+
// console.log(account.balance.coins, 'coins before');
247+
// if (isOurTxLastTx) console.log(accountAfter.balance.coins, 'coins after');
223248

224249
// 5. prep. emulator
225250

@@ -242,7 +267,7 @@ export async function getEmulationWithStack(
242267

243268
let _txRes = _executor.runTransaction({
244269
config: blockConfig,
245-
libs: null,
270+
libs,
246271
verbosity: _withStack ? 'full_location_stack_verbose' : 'short',
247272
shardAccount: _shardAccountStr,
248273
message: beginCell().store(storeMessage(_msg)).endCell(),
@@ -402,20 +427,20 @@ export async function getEmulationWithStack(
402427
);
403428
const endBalance = parsedShardAccount.account?.storage.balance.coins || 0n;
404429

405-
if (isOurTxLastTx) {
406-
// we dont know mainnet balance if its not last tx in block
407-
const balanceCheck = endBalance === BigInt(accountAfter.balance.coins);
408-
if (!balanceCheck) {
409-
console.error(
410-
`Balance check failed, expected ${accountAfter.balance.coins} got ${endBalance}`
411-
);
412-
} else {
413-
console.log('Balance check ok');
414-
}
415-
} else {
416-
console.log('Balance check skipped');
417-
console.log(endBalance, 'end balance');
418-
}
430+
// if (isOurTxLastTx) {
431+
// // we dont know mainnet balance if its not last tx in block
432+
// const balanceCheck = endBalance === BigInt(accountAfter.balance.coins);
433+
// if (!balanceCheck) {
434+
// console.error(
435+
// `Balance check failed, expected ${accountAfter.balance.coins} got ${endBalance}`
436+
// );
437+
// } else {
438+
// console.log('Balance check ok');
439+
// }
440+
// } else {
441+
// console.log('Balance check skipped');
442+
// console.log(endBalance, 'end balance');
443+
// }
419444

420445
const theTx = loadTransaction(
421446
Cell.fromBase64(txResCorrect.result.transaction).asSlice()
@@ -491,9 +516,6 @@ export async function getEmulationWithStack(
491516
gasFees: computePhase.gasFees,
492517
};
493518

494-
console.log(parsedShardAccount);
495-
console.log(accountAfter);
496-
497519
return {
498520
sender: src,
499521
contract: dest,

src/runner/utils.ts

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Address } from '@ton/core';
1+
import { Address, Cell } from '@ton/core';
22
import axios, { AxiosInstance, AxiosResponse } from 'axios';
33
import { z } from 'zod';
44
import {
@@ -67,7 +67,6 @@ export async function mcSeqnoByShard(
6767
block.root_hash
6868
);
6969
}
70-
console.log(block);
7170
return {
7271
mcSeqno: block.masterchain_block_ref.seqno,
7372
randSeed: Buffer.from(block.rand_seed, 'base64'),
@@ -78,6 +77,31 @@ export async function mcSeqnoByShard(
7877
}
7978
}
8079

80+
export async function getLib(libhash: string, testnet: boolean): Promise<Cell> {
81+
// gets a library by its hash from dton's graphql
82+
const dtonEndpoint = `https://${testnet ? 'testnet.' : ''}dton.io/graphql`;
83+
const graphqlQuery = {
84+
query: `
85+
query fetchAuthor {
86+
get_lib(lib_hash: "${libhash}")
87+
}
88+
`,
89+
variables: {},
90+
};
91+
try {
92+
const res = await axios.post(dtonEndpoint, graphqlQuery, {
93+
headers: {
94+
'Content-Type': 'application/json',
95+
},
96+
});
97+
const libB64 = res.data.data.get_lib;
98+
return Cell.fromBase64(libB64);
99+
} catch (error) {
100+
console.error('Error fetching library:', error);
101+
throw error;
102+
}
103+
}
104+
81105
export async function linkToTx(
82106
txLink: string,
83107
testnet: boolean

0 commit comments

Comments
 (0)