solana.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. // SPDX-License-Identifier: Apache-2.0
  2. #include <stdint.h>
  3. #include <stddef.h>
  4. #include "stdlib.h"
  5. #include "solana_sdk.h"
  6. extern uint64_t solang_dispatch(SolParameters *param);
  7. extern void __init_heap();
  8. // The address 'SysvarC1ock11111111111111111111111111111111' base58 decoded
  9. static const SolPubkey clock_address = {0x06, 0xa7, 0xd5, 0x17, 0x18, 0xc7, 0x74, 0xc9, 0x28, 0x56, 0x63,
  10. 0x98, 0x69, 0x1d, 0x5e, 0xb6, 0x8b, 0x5e, 0xb8, 0xa3, 0x9b, 0x4b,
  11. 0x6d, 0x5c, 0x73, 0x55, 0x5b, 0x21, 0x00, 0x00, 0x00, 0x00};
  12. // The address 'Sysvar1nstructions1111111111111111111111111' base58 decoded
  13. static const SolPubkey instructions_address = {0x06, 0xa7, 0xd5, 0x17, 0x18, 0x7b, 0xd1, 0x66, 0x35, 0xda, 0xd4,
  14. 0x04, 0x55, 0xfd, 0xc2, 0xc0, 0xc1, 0x24, 0xc6, 0x8f, 0x21, 0x56,
  15. 0x75, 0xa5, 0xdb, 0xba, 0xcb, 0x5f, 0x08, 0x00, 0x00, 0x00};
  16. // The address 'Ed25519SigVerify111111111111111111111111111' base58 decoded
  17. static const SolPubkey ed25519_address = {0x03, 0x7d, 0x46, 0xd6, 0x7c, 0x93, 0xfb, 0xbe, 0x12, 0xf9, 0x42,
  18. 0x8f, 0x83, 0x8d, 0x40, 0xff, 0x05, 0x70, 0x74, 0x49, 0x27, 0xf4,
  19. 0x8a, 0x64, 0xfc, 0xca, 0x70, 0x44, 0x80, 0x00, 0x00, 0x00};
  20. #ifndef TEST
  21. uint64_t entrypoint(const uint8_t *input)
  22. {
  23. SolParameters params;
  24. uint64_t ret = sol_deserialize(input, &params);
  25. if (ret)
  26. {
  27. return ret;
  28. }
  29. params.ka_clock = NULL;
  30. params.ka_instructions = NULL;
  31. for (int account_no = 0; account_no < params.ka_num; account_no++)
  32. {
  33. const SolAccountInfo *acc = &params.ka[account_no];
  34. if (SolPubkey_same(&clock_address, acc->key))
  35. {
  36. params.ka_clock = acc;
  37. }
  38. else if (SolPubkey_same(&instructions_address, acc->key))
  39. {
  40. params.ka_instructions = acc;
  41. }
  42. }
  43. __init_heap();
  44. return solang_dispatch(&params);
  45. }
  46. uint64_t sol_invoke_signed_c(const SolInstruction *instruction, const SolAccountInfo *account_infos,
  47. int account_infos_len, const SolSignerSeeds *signers_seeds, int signers_seeds_len);
  48. // Calls an external function when 'program_id' is NULL or
  49. // creates a new contract and calls its constructor.
  50. uint64_t external_call(uint8_t *input, uint32_t input_len, SolPubkey *program_id, const SolSignerSeeds *seeds,
  51. int seeds_len, SolParameters *params)
  52. {
  53. SolAccountMeta metas[10];
  54. SolInstruction instruction = {
  55. .program_id = program_id,
  56. .accounts = metas,
  57. .account_len = params->ka_num,
  58. .data = input,
  59. .data_len = input_len,
  60. };
  61. // When the '{accounts: ...}' call argument is missing, we pass on all the accounts in the transaction.
  62. for (int account_no = 0; account_no < params->ka_num; account_no++)
  63. {
  64. SolAccountInfo *acc = &params->ka[account_no];
  65. metas[account_no].pubkey = acc->key;
  66. metas[account_no].is_writable = acc->is_writable;
  67. metas[account_no].is_signer = acc->is_signer;
  68. }
  69. return sol_invoke_signed_c(&instruction, params->ka, params->ka_num, seeds, seeds_len);
  70. }
  71. uint64_t *sol_account_lamport(uint8_t *address, SolParameters *params)
  72. {
  73. SolPubkey *pubkey = (SolPubkey *)address;
  74. for (int i = 0; i < params->ka_num; i++)
  75. {
  76. if (SolPubkey_same(pubkey, params->ka[i].key))
  77. {
  78. return params->ka[i].lamports;
  79. }
  80. }
  81. sol_log_pubkey(pubkey);
  82. sol_log("account missing from transaction");
  83. sol_panic();
  84. return NULL;
  85. }
  86. void sol_transfer(uint8_t *to_address, uint64_t lamports, SolParameters *params)
  87. {
  88. uint64_t *from = params->ka[0].lamports;
  89. uint64_t *to = sol_account_lamport(to_address, params);
  90. uint64_t from_balance;
  91. uint64_t to_balance;
  92. if (__builtin_sub_overflow(*from, lamports, &from_balance))
  93. {
  94. sol_log("sender does not have enough balance");
  95. sol_panic();
  96. }
  97. if (__builtin_add_overflow(*to, lamports, &to_balance))
  98. {
  99. sol_log("recipient lamports overflows");
  100. sol_panic();
  101. }
  102. *from = from_balance;
  103. *to = to_balance;
  104. }
  105. bool sol_try_transfer(uint8_t *to_address, uint64_t lamports, SolParameters *params)
  106. {
  107. uint64_t *from = params->ka[0].lamports;
  108. uint64_t *to = sol_account_lamport(to_address, params);
  109. uint64_t from_balance;
  110. uint64_t to_balance;
  111. if (__builtin_sub_overflow(*from, lamports, &from_balance))
  112. {
  113. return false;
  114. }
  115. if (__builtin_add_overflow(*to, lamports, &to_balance))
  116. {
  117. return false;
  118. }
  119. *from = from_balance;
  120. *to = to_balance;
  121. return true;
  122. }
  123. #endif
  124. uint64_t address_hash(uint8_t data[32])
  125. {
  126. uint64_t hash = 0;
  127. uint32_t i;
  128. for (i = 0; i < 32; i++)
  129. {
  130. hash += data[i];
  131. }
  132. return hash;
  133. }
  134. bool address_equal(void *a, void *b)
  135. {
  136. uint64_t *left = a;
  137. uint64_t *right = b;
  138. for (uint32_t i = 0; i < 4; i++)
  139. {
  140. if (left[i] != right[i])
  141. {
  142. return false;
  143. }
  144. }
  145. return true;
  146. }
  147. struct ed25519_instruction_sig
  148. {
  149. uint16_t signature_offset;
  150. uint16_t signature_instruction_index;
  151. uint16_t public_key_offset;
  152. uint16_t public_key_instruction_index;
  153. uint16_t message_offset;
  154. uint16_t message_size;
  155. uint16_t message_instruction_index;
  156. uint8_t public_key[SIZE_PUBKEY];
  157. uint8_t signature[64];
  158. uint8_t message[0];
  159. };
  160. struct ed25519_instruction
  161. {
  162. uint8_t num_signatures;
  163. uint8_t padding;
  164. struct ed25519_instruction_sig sig[0];
  165. };
  166. uint64_t signature_verify(uint8_t *public_key, struct vector *message, struct vector *signature, SolParameters *params)
  167. {
  168. if (params->ka_instructions)
  169. {
  170. uint16_t *data = (uint16_t *)params->ka_instructions->data;
  171. uint64_t instr_count = data[0];
  172. // for each instruction
  173. for (uint64_t instr_no = 0; instr_no < instr_count; instr_no++)
  174. {
  175. uint8_t *instr = params->ka_instructions->data + data[1 + instr_no];
  176. // step over the accounts
  177. uint64_t accounts = *((uint16_t *)instr);
  178. instr += accounts * 33 + 2;
  179. if (sol_memcmp(&ed25519_address, instr, sizeof(ed25519_address)))
  180. {
  181. continue;
  182. }
  183. // step over program_id and length
  184. instr += 2 + 32;
  185. struct ed25519_instruction *ed25519 = (struct ed25519_instruction *)instr;
  186. for (uint64_t sig_no = 0; sig_no < ed25519->num_signatures; sig_no++)
  187. {
  188. struct ed25519_instruction_sig *sig = &ed25519->sig[sig_no];
  189. if (sig->public_key_instruction_index != instr_no || sig->signature_instruction_index != instr_no ||
  190. sig->message_instruction_index != instr_no)
  191. continue;
  192. if (sol_memcmp(public_key, instr + sig->public_key_offset, SIZE_PUBKEY))
  193. {
  194. continue;
  195. }
  196. if (sol_memcmp(signature->data, instr + sig->signature_offset, 64))
  197. {
  198. continue;
  199. }
  200. if (sig->message_size != message->len)
  201. {
  202. continue;
  203. }
  204. if (sol_memcmp(message->data, instr + sig->message_offset, message->len))
  205. {
  206. continue;
  207. }
  208. return 0;
  209. }
  210. }
  211. }
  212. sol_log("could not find verified signature");
  213. return 1;
  214. }
  215. struct clock_layout
  216. {
  217. uint64_t slot;
  218. uint64_t epoch_start_timestamp;
  219. uint64_t epoch;
  220. uint64_t leader_schedule_epoch;
  221. uint64_t unix_timestamp;
  222. };
  223. struct clock_layout *sol_clock(SolParameters *params)
  224. {
  225. if (!params->ka_clock)
  226. {
  227. sol_log("clock account missing from transaction");
  228. sol_panic();
  229. }
  230. struct clock_layout *clock_data = (struct clock_layout *)params->ka_clock->data;
  231. return clock_data;
  232. }
  233. struct account_data_header
  234. {
  235. uint32_t magic;
  236. uint32_t returndata_len;
  237. uint32_t returndata_offset;
  238. uint32_t heap_offset;
  239. };
  240. // Simple heap for account data
  241. //
  242. // The heap is a doubly-linked list of objects, so we can merge with neighbours when we free.
  243. // We should use offsets rather than pointers as the layout in memory will be different each
  244. // time it is called.
  245. // We don't expect the account data to exceed 4GB so we use 32 bit offsets.
  246. // The account data can grow so the last entry always has length = 0 and offset_next = 0.
  247. struct chunk
  248. {
  249. uint32_t offset_next, offset_prev;
  250. uint32_t length;
  251. uint32_t allocated;
  252. };
  253. #define ROUND_UP(n, d) (((n) + (d)-1) & ~(d - 1))
  254. uint64_t account_data_alloc(SolAccountInfo *ai, uint32_t size, uint32_t *res)
  255. {
  256. void *data = ai->data;
  257. struct account_data_header *hdr = data;
  258. if (!size)
  259. {
  260. *res = 0;
  261. return 0;
  262. }
  263. uint32_t offset = hdr->heap_offset;
  264. uint32_t alloc_size = ROUND_UP(size, 8);
  265. uint32_t offset_prev = 0;
  266. for (;;)
  267. {
  268. struct chunk *chunk = data + offset;
  269. if (!chunk->allocated)
  270. {
  271. if (!chunk->length)
  272. {
  273. offset += sizeof(struct chunk);
  274. if (offset + alloc_size + sizeof(struct chunk) >= ai->data_len)
  275. {
  276. return ERROR_ACCOUNT_DATA_TOO_SMALL;
  277. }
  278. chunk->offset_next = offset + alloc_size;
  279. chunk->offset_prev = offset_prev;
  280. chunk->allocated = true;
  281. chunk->length = size;
  282. struct chunk *next = data + chunk->offset_next;
  283. next->offset_prev = offset - sizeof(struct chunk);
  284. next->length = 0;
  285. next->offset_next = 0;
  286. next->allocated = false;
  287. *res = offset;
  288. return 0;
  289. }
  290. else if (chunk->length < alloc_size)
  291. {
  292. // too small
  293. }
  294. else if (alloc_size + sizeof(struct chunk) + 8 > chunk->length)
  295. {
  296. // just right
  297. chunk->allocated = true;
  298. chunk->length = size;
  299. *res = offset + sizeof(struct chunk);
  300. return 0;
  301. }
  302. else
  303. {
  304. // too big, split
  305. uint32_t next = chunk->offset_next;
  306. uint32_t prev = offset;
  307. uint32_t next_offset = offset + sizeof(struct chunk) + alloc_size;
  308. chunk->offset_next = next_offset;
  309. chunk->length = size;
  310. chunk->allocated = true;
  311. chunk = data + next_offset;
  312. chunk->offset_prev = prev;
  313. chunk->offset_next = next;
  314. chunk->length = next - next_offset - sizeof(struct chunk);
  315. chunk->allocated = false;
  316. if (next)
  317. {
  318. struct chunk *chunk = data + next;
  319. chunk->offset_prev = next_offset;
  320. }
  321. *res = offset + sizeof(struct chunk);
  322. return 0;
  323. }
  324. }
  325. offset_prev = offset;
  326. offset = chunk->offset_next;
  327. }
  328. }
  329. uint32_t account_data_len(void *data, uint32_t offset)
  330. {
  331. // Nothing to do
  332. if (!offset)
  333. return 0;
  334. offset -= sizeof(struct chunk);
  335. struct chunk *chunk = data + offset;
  336. return chunk->length;
  337. }
  338. void account_data_free(void *data, uint32_t offset)
  339. {
  340. // Nothing to do
  341. if (!offset)
  342. return;
  343. offset -= sizeof(struct chunk);
  344. struct chunk *chunk = data + offset;
  345. chunk->allocated = false;
  346. // merge with previous chunk?
  347. if (chunk->offset_prev)
  348. {
  349. struct chunk *prev = data + chunk->offset_prev;
  350. if (!prev->allocated)
  351. {
  352. // merge
  353. offset = chunk->offset_prev;
  354. if (chunk->offset_next)
  355. {
  356. prev->length = chunk->offset_next - offset - sizeof(struct chunk);
  357. prev->offset_next = chunk->offset_next;
  358. struct chunk *next = data + chunk->offset_next;
  359. next->offset_prev = offset;
  360. }
  361. else
  362. {
  363. prev->offset_next = 0;
  364. prev->length = 0;
  365. }
  366. chunk = prev;
  367. }
  368. }
  369. // merge with next chunk?
  370. if (chunk->offset_next)
  371. {
  372. struct chunk *next = data + chunk->offset_next;
  373. if (!next->allocated)
  374. {
  375. // merge
  376. if (next->offset_next)
  377. {
  378. chunk->offset_next = next->offset_next;
  379. chunk->length = chunk->offset_next - offset - sizeof(struct chunk);
  380. struct chunk *next = data + chunk->offset_next;
  381. next->offset_prev = offset;
  382. }
  383. else
  384. {
  385. chunk->offset_next = 0;
  386. chunk->length = 0;
  387. }
  388. }
  389. }
  390. }
  391. uint64_t account_data_realloc(SolAccountInfo *ai, uint32_t offset, uint32_t size, uint32_t *res)
  392. {
  393. if (!size)
  394. {
  395. account_data_free(ai->data, offset);
  396. *res = 0;
  397. return 0;
  398. }
  399. if (!offset)
  400. {
  401. return account_data_alloc(ai, size, res);
  402. }
  403. void *data = ai->data;
  404. uint32_t chunk_offset = offset - sizeof(struct chunk);
  405. struct chunk *chunk = data + chunk_offset;
  406. struct chunk *next = data + chunk->offset_next;
  407. uint32_t existing_size = chunk->offset_next - offset;
  408. uint32_t alloc_size = ROUND_UP(size, 8);
  409. // 1. Is the existing chunk big enough
  410. if (size <= existing_size)
  411. {
  412. chunk->length = size;
  413. // can we free up some space
  414. if (existing_size >= alloc_size + sizeof(struct chunk) + 8)
  415. {
  416. uint32_t new_next_offset = offset + alloc_size;
  417. if (!next->allocated)
  418. {
  419. // merge with next chunk
  420. if (!next->offset_next)
  421. {
  422. // the trailing free chunk
  423. chunk->offset_next = new_next_offset;
  424. next = data + new_next_offset;
  425. next->offset_prev = chunk_offset;
  426. next->offset_next = 0;
  427. next->allocated = false;
  428. next->length = 0;
  429. }
  430. else
  431. {
  432. // merge with next chunk
  433. chunk->offset_next = new_next_offset;
  434. uint32_t offset_next_next = next->offset_next;
  435. next = data + new_next_offset;
  436. next->offset_prev = chunk_offset;
  437. next->offset_next = offset_next_next;
  438. next->allocated = false;
  439. next->length = offset_next_next - new_next_offset - sizeof(struct chunk);
  440. next = data + offset_next_next;
  441. next->offset_prev = new_next_offset;
  442. }
  443. }
  444. else
  445. {
  446. // insert a new chunk
  447. uint32_t offset_next_next = chunk->offset_next;
  448. chunk->offset_next = new_next_offset;
  449. next = data + new_next_offset;
  450. next->offset_prev = chunk_offset;
  451. next->offset_next = offset_next_next;
  452. next->allocated = false;
  453. next->length = offset_next_next - new_next_offset - sizeof(struct chunk);
  454. next = data + offset_next_next;
  455. next->offset_prev = new_next_offset;
  456. }
  457. }
  458. *res = offset;
  459. return 0;
  460. }
  461. // 2. Can we use the next chunk to expand our chunk to fit
  462. // Note because we always merge neighbours, free chunks do not have free
  463. // neighbours.
  464. if (!next->allocated)
  465. {
  466. if (next->offset_next)
  467. {
  468. uint32_t merged_size = next->offset_next - offset;
  469. if (size < merged_size)
  470. {
  471. if (merged_size - alloc_size < 8 + sizeof(struct chunk))
  472. {
  473. // merge the two chunks
  474. chunk->offset_next = next->offset_next;
  475. chunk->length = size;
  476. next = data + chunk->offset_next;
  477. next->offset_prev = chunk_offset;
  478. }
  479. else
  480. {
  481. // expand our chunk to fit and shrink the next chunk
  482. uint32_t offset_next = offset + alloc_size;
  483. uint32_t offset_next_next = next->offset_next;
  484. chunk->offset_next = offset_next;
  485. chunk->length = size;
  486. next = data + offset_next;
  487. next->offset_prev = chunk_offset;
  488. next->offset_next = offset_next_next;
  489. next->length = offset_next_next - offset_next - sizeof(struct chunk);
  490. next->allocated = false;
  491. next = data + offset_next_next;
  492. next->offset_prev = offset_next;
  493. }
  494. *res = offset;
  495. return 0;
  496. }
  497. }
  498. else
  499. {
  500. if (offset + alloc_size + sizeof(struct chunk) < ai->data_len)
  501. {
  502. chunk->offset_next = offset + alloc_size;
  503. chunk->length = size;
  504. next = data + chunk->offset_next;
  505. next->offset_prev = chunk_offset;
  506. next->offset_next = 0;
  507. next->allocated = false;
  508. next->length = 0;
  509. *res = offset;
  510. return 0;
  511. }
  512. }
  513. }
  514. uint32_t old_length = account_data_len(data, offset);
  515. uint32_t new_offset;
  516. uint64_t rc = account_data_alloc(ai, size, &new_offset);
  517. if (rc)
  518. return rc;
  519. __memcpy(data + new_offset, data + offset, old_length);
  520. account_data_free(data, offset);
  521. *res = new_offset;
  522. return 0;
  523. }
  524. #ifdef TEST
  525. // To run the test:
  526. // clang -DTEST -DSOL_TEST -O3 -Wall solana.c stdlib.c -o test && ./test
  527. #include <assert.h>
  528. #include <string.h>
  529. #include <stdlib.h>
  530. #include <time.h>
  531. void validate_heap(void *data, uint32_t offs[100], uint32_t lens[100])
  532. {
  533. struct account_data_header *hdr = data;
  534. uint32_t offset = hdr->heap_offset;
  535. uint32_t last_offset = 0;
  536. for (;;)
  537. {
  538. struct chunk *chk = data + offset;
  539. // printf("chunk: offset:%x prev:%x next:%x length:%x allocated:%d\n", offset, chk->offset_prev, chk->offset_next, chk->length, chk->allocated);
  540. if (chk->length == 0 || chk->offset_next == 0)
  541. {
  542. assert(chk->length == 0 && chk->offset_next == 0 && chk->offset_prev == last_offset);
  543. // printf("last object at 0x%08x\n", offset);
  544. return;
  545. }
  546. assert(chk->offset_prev == last_offset && chk->length != 0);
  547. // printf("found object length %x at 0x%08lx allocated %d\n", chk->length, offset + sizeof(struct chunk), chk->allocated);
  548. assert(chk->offset_next - offset - sizeof(struct chunk) >= chk->length);
  549. if (chk->allocated)
  550. {
  551. bool found = false;
  552. uint32_t off = offset + sizeof(struct chunk);
  553. for (int i = 0; i < 100; i++)
  554. {
  555. if (offs[i] == off)
  556. {
  557. assert(!found);
  558. found = true;
  559. uint8_t *mem = data + off;
  560. for (int x = 0; x < lens[i]; x++)
  561. {
  562. assert(mem[x] == i);
  563. }
  564. }
  565. }
  566. assert(found);
  567. }
  568. else
  569. {
  570. // make sure we do not have this in our allocated list
  571. uint32_t off = offset + sizeof(struct chunk);
  572. for (int i = 0; i < 100; i++)
  573. {
  574. assert(offs[i] != off);
  575. }
  576. }
  577. last_offset = offset;
  578. offset = chk->offset_next;
  579. }
  580. }
  581. int main()
  582. {
  583. uint8_t data[0x10000];
  584. SolAccountInfo ai;
  585. ai.data = data;
  586. ai.data_len = sizeof(data);
  587. uint32_t offs[100], lens[100];
  588. uint32_t allocs = 0;
  589. memset(data, 0, sizeof(data));
  590. struct account_data_header *hdr = data;
  591. hdr->magic = 0x41424344;
  592. hdr->heap_offset = 0x20;
  593. memset(offs, 0, sizeof(offs));
  594. int seed = time(NULL);
  595. printf("seed: %d\n", seed);
  596. srand(seed);
  597. uint32_t new_offset;
  598. uint64_t status;
  599. for (;;)
  600. {
  601. validate_heap(data, offs, lens);
  602. int n = rand() % 100;
  603. if (offs[n] == 0)
  604. {
  605. // printf("STEP: alloc %d\n", n);
  606. status = account_data_alloc(&ai, 100, &new_offset);
  607. assert(status == 0);
  608. offs[n] = new_offset;
  609. memset(data + offs[n], n, 100);
  610. lens[n] = 100;
  611. }
  612. else if (rand() % 2)
  613. {
  614. // printf("STEP: free %d (0x%x)\n", n, offs[n]);
  615. account_data_free(ai.data, offs[n]);
  616. offs[n] = 0;
  617. }
  618. else
  619. {
  620. // printf("STEP: realloc %d (0x%x)\n", n, offs[n]);
  621. int size = (rand() % 200) + 10;
  622. int old_size = account_data_len(ai.data, offs[n]);
  623. status = account_data_realloc(&ai, offs[n], size, &new_offset);
  624. assert(status == 0);
  625. offs[n] = new_offset;
  626. if (size > old_size)
  627. memset(data + offs[n] + old_size, n, size - old_size);
  628. lens[n] = size;
  629. }
  630. if (time(NULL) - seed > 120)
  631. {
  632. printf("No error found after running for two minutes\n");
  633. break;
  634. }
  635. }
  636. }
  637. void sol_panic_(const char *s, uint64_t len, uint64_t line, uint64_t column)
  638. {
  639. printf("panic: %s line %lld", s, line);
  640. }
  641. #endif