zero-copy.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. const anchor = require("@project-serum/anchor");
  2. const { assert } = require("chai");
  3. const nativeAssert = require("assert");
  4. const PublicKey = anchor.web3.PublicKey;
  5. const BN = anchor.BN;
  6. describe("zero-copy", () => {
  7. // Configure the client to use the local cluster.
  8. anchor.setProvider(anchor.Provider.env());
  9. const program = anchor.workspace.ZeroCopy;
  10. const programCpi = anchor.workspace.ZeroCpi;
  11. const foo = anchor.web3.Keypair.generate();
  12. it("Is creates a zero copy account", async () => {
  13. await program.rpc.createFoo({
  14. accounts: {
  15. foo: foo.publicKey,
  16. authority: program.provider.wallet.publicKey,
  17. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  18. },
  19. instructions: [await program.account.foo.createInstruction(foo)],
  20. signers: [foo],
  21. });
  22. const account = await program.account.foo.fetch(foo.publicKey);
  23. assert.strictEqual(
  24. JSON.stringify(account.authority.toBuffer()),
  25. JSON.stringify(program.provider.wallet.publicKey.toBuffer())
  26. );
  27. assert.strictEqual(account.data.toNumber(), 0);
  28. assert.strictEqual(account.secondData.toNumber(), 0);
  29. assert.strictEqual(
  30. JSON.stringify(account.secondAuthority),
  31. JSON.stringify([...program.provider.wallet.publicKey.toBuffer()])
  32. );
  33. });
  34. it("Updates a zero copy account field", async () => {
  35. await program.rpc.updateFoo(new BN(1234), {
  36. accounts: {
  37. foo: foo.publicKey,
  38. authority: program.provider.wallet.publicKey,
  39. },
  40. });
  41. const account = await program.account.foo.fetch(foo.publicKey);
  42. assert.strictEqual(
  43. JSON.stringify(account.authority.toBuffer()),
  44. JSON.stringify(program.provider.wallet.publicKey.toBuffer())
  45. );
  46. assert.strictEqual(account.data.toNumber(), 1234);
  47. assert.strictEqual(account.secondData.toNumber(), 0);
  48. assert.strictEqual(
  49. JSON.stringify(account.secondAuthority),
  50. JSON.stringify([...program.provider.wallet.publicKey.toBuffer()])
  51. );
  52. });
  53. it("Updates a a second zero copy account field", async () => {
  54. await program.rpc.updateFooSecond(new BN(55), {
  55. accounts: {
  56. foo: foo.publicKey,
  57. secondAuthority: program.provider.wallet.publicKey,
  58. },
  59. });
  60. const account = await program.account.foo.fetch(foo.publicKey);
  61. assert.strictEqual(
  62. JSON.stringify(account.authority.toBuffer()),
  63. JSON.stringify(program.provider.wallet.publicKey.toBuffer())
  64. );
  65. assert.strictEqual(account.data.toNumber(), 1234);
  66. assert.strictEqual(account.secondData.toNumber(), 55);
  67. assert.strictEqual(
  68. JSON.stringify(account.secondAuthority),
  69. JSON.stringify([...program.provider.wallet.publicKey.toBuffer()])
  70. );
  71. });
  72. it("Creates an associated zero copy account", async () => {
  73. await program.rpc.createBar({
  74. accounts: {
  75. bar: (
  76. await PublicKey.findProgramAddress(
  77. [
  78. program.provider.wallet.publicKey.toBuffer(),
  79. foo.publicKey.toBuffer(),
  80. ],
  81. program.programId
  82. )
  83. )[0],
  84. authority: program.provider.wallet.publicKey,
  85. foo: foo.publicKey,
  86. systemProgram: anchor.web3.SystemProgram.programId,
  87. },
  88. });
  89. const bar = (
  90. await PublicKey.findProgramAddress(
  91. [
  92. program.provider.wallet.publicKey.toBuffer(),
  93. foo.publicKey.toBuffer(),
  94. ],
  95. program.programId
  96. )
  97. )[0];
  98. const barAccount = await program.account.bar.fetch(bar);
  99. assert.isTrue(
  100. barAccount.authority.equals(program.provider.wallet.publicKey)
  101. );
  102. assert.strictEqual(barAccount.data.toNumber(), 0);
  103. });
  104. it("Updates an associated zero copy account", async () => {
  105. const bar = (
  106. await PublicKey.findProgramAddress(
  107. [
  108. program.provider.wallet.publicKey.toBuffer(),
  109. foo.publicKey.toBuffer(),
  110. ],
  111. program.programId
  112. )
  113. )[0];
  114. await program.rpc.updateBar(new BN(99), {
  115. accounts: {
  116. bar,
  117. authority: program.provider.wallet.publicKey,
  118. foo: foo.publicKey,
  119. },
  120. });
  121. const barAccount = await program.account.bar.fetch(bar);
  122. assert.isTrue(
  123. barAccount.authority.equals(program.provider.wallet.publicKey)
  124. );
  125. assert.strictEqual(barAccount.data.toNumber(), 99);
  126. // Check zero_copy CPI
  127. await programCpi.rpc.checkCpi(new BN(1337), {
  128. accounts: {
  129. bar,
  130. authority: program.provider.wallet.publicKey,
  131. foo: foo.publicKey,
  132. zeroCopyProgram: program.programId,
  133. },
  134. });
  135. const barAccountAfterCpi = await program.account.bar.fetch(bar);
  136. assert.isTrue(
  137. barAccountAfterCpi.authority.equals(program.provider.wallet.publicKey)
  138. );
  139. assert.strictEqual(barAccountAfterCpi.data.toNumber(), 1337);
  140. });
  141. const eventQ = anchor.web3.Keypair.generate();
  142. const size = 1000000 + 8; // Account size in bytes.
  143. it("Creates a large event queue", async () => {
  144. await program.rpc.createLargeAccount({
  145. accounts: {
  146. eventQ: eventQ.publicKey,
  147. rent: anchor.web3.SYSVAR_RENT_PUBKEY,
  148. },
  149. instructions: [
  150. await program.account.eventQ.createInstruction(eventQ, size),
  151. ],
  152. signers: [eventQ],
  153. });
  154. const account = await program.account.eventQ.fetch(eventQ.publicKey);
  155. assert.strictEqual(account.events.length, 25000);
  156. account.events.forEach((event) => {
  157. assert.isTrue(event.from.equals(PublicKey.default));
  158. assert.strictEqual(event.data.toNumber(), 0);
  159. });
  160. });
  161. it("Updates a large event queue", async () => {
  162. // Set index 0.
  163. await program.rpc.updateLargeAccount(0, new BN(48), {
  164. accounts: {
  165. eventQ: eventQ.publicKey,
  166. from: program.provider.wallet.publicKey,
  167. },
  168. });
  169. // Verify update.
  170. let account = await program.account.eventQ.fetch(eventQ.publicKey);
  171. assert.strictEqual(account.events.length, 25000);
  172. account.events.forEach((event, idx) => {
  173. if (idx === 0) {
  174. assert.isTrue(event.from.equals(program.provider.wallet.publicKey));
  175. assert.strictEqual(event.data.toNumber(), 48);
  176. } else {
  177. assert.isTrue(event.from.equals(PublicKey.default));
  178. assert.strictEqual(event.data.toNumber(), 0);
  179. }
  180. });
  181. // Set index 11111.
  182. await program.rpc.updateLargeAccount(11111, new BN(1234), {
  183. accounts: {
  184. eventQ: eventQ.publicKey,
  185. from: program.provider.wallet.publicKey,
  186. },
  187. });
  188. // Verify update.
  189. account = await program.account.eventQ.fetch(eventQ.publicKey);
  190. assert.strictEqual(account.events.length, 25000);
  191. account.events.forEach((event, idx) => {
  192. if (idx === 0) {
  193. assert.isTrue(event.from.equals(program.provider.wallet.publicKey));
  194. assert.strictEqual(event.data.toNumber(), 48);
  195. } else if (idx === 11111) {
  196. assert.isTrue(event.from.equals(program.provider.wallet.publicKey));
  197. assert.strictEqual(event.data.toNumber(), 1234);
  198. } else {
  199. assert.isTrue(event.from.equals(PublicKey.default));
  200. assert.strictEqual(event.data.toNumber(), 0);
  201. }
  202. });
  203. // Set last index.
  204. await program.rpc.updateLargeAccount(24999, new BN(99), {
  205. accounts: {
  206. eventQ: eventQ.publicKey,
  207. from: program.provider.wallet.publicKey,
  208. },
  209. });
  210. // Verify update.
  211. account = await program.account.eventQ.fetch(eventQ.publicKey);
  212. assert.strictEqual(account.events.length, 25000);
  213. account.events.forEach((event, idx) => {
  214. if (idx === 0) {
  215. assert.isTrue(event.from.equals(program.provider.wallet.publicKey));
  216. assert.strictEqual(event.data.toNumber(), 48);
  217. } else if (idx === 11111) {
  218. assert.isTrue(event.from.equals(program.provider.wallet.publicKey));
  219. assert.strictEqual(event.data.toNumber(), 1234);
  220. } else if (idx === 24999) {
  221. assert.isTrue(event.from.equals(program.provider.wallet.publicKey));
  222. assert.strictEqual(event.data.toNumber(), 99);
  223. } else {
  224. assert.isTrue(event.from.equals(PublicKey.default));
  225. assert.strictEqual(event.data.toNumber(), 0);
  226. }
  227. });
  228. });
  229. it("Errors when setting an out of bounds index", async () => {
  230. // Fail to set non existing index.
  231. await nativeAssert.rejects(
  232. async () => {
  233. await program.rpc.updateLargeAccount(25000, new BN(1), {
  234. accounts: {
  235. eventQ: eventQ.publicKey,
  236. from: program.provider.wallet.publicKey,
  237. },
  238. });
  239. },
  240. (err) => {
  241. console.log("err", err);
  242. return true;
  243. }
  244. );
  245. });
  246. });