solana.c 23 KB

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