From fc345ef4cf6c2277b9578ec922d82494add0a59b Mon Sep 17 00:00:00 2001 From: Zewasik Date: Fri, 20 Dec 2024 11:57:03 +0200 Subject: [PATCH 1/2] change metadata usage to raw hex payload skip tests with meta --- api/programs/Cargo.lock | 1 + api/programs/test/Cargo.toml | 1 + api/programs/test/src/lib.rs | 74 ++++++++++++++++++++++++++++++-- api/test/Message.test.ts | 62 +++++++++++---------------- api/test/Program.test.ts | 60 +++++++++++--------------- api/test/Voucher.test.ts | 83 ++++++++++++------------------------ api/test/Waitlist.test.ts | 16 +++++-- api/test/utilsFunctions.ts | 33 ++++++++++++++ 8 files changed, 193 insertions(+), 137 deletions(-) diff --git a/api/programs/Cargo.lock b/api/programs/Cargo.lock index b49dcfd260..3fd07a7bad 100644 --- a/api/programs/Cargo.lock +++ b/api/programs/Cargo.lock @@ -1127,6 +1127,7 @@ version = "0.1.0" dependencies = [ "gear-wasm-builder", "gstd", + "parity-scale-codec", ] [[package]] diff --git a/api/programs/test/Cargo.toml b/api/programs/test/Cargo.toml index 4213a15adc..87acd6ebc1 100644 --- a/api/programs/test/Cargo.toml +++ b/api/programs/test/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] gstd.workspace = true +codec.workspace = true [build-dependencies] gear-wasm-builder.workspace = true diff --git a/api/programs/test/src/lib.rs b/api/programs/test/src/lib.rs index 89c4dea826..ed57efa9cf 100644 --- a/api/programs/test/src/lib.rs +++ b/api/programs/test/src/lib.rs @@ -1,14 +1,80 @@ #![no_std] -extern crate gstd; +use codec::{Decode, Encode}; +use gstd::{ + collections::{BTreeMap, BTreeSet}, + msg, + prelude::*, +}; + +#[derive(Decode, Encode)] +pub enum Action { + One(Option), + Two((u8, u16)), + Three(), + Four(), + Input(String), + Wait(), +} + +#[derive(Decode, Encode)] +pub struct InputStruct { + pub input: String, +} + +#[derive(Encode, Decode, Clone)] +pub struct EmptyStruct { + pub empty: (), +} #[no_mangle] unsafe extern "C" fn init() { - gstd::msg::reply("ok", 0).unwrap(); -} + let _: BTreeSet = msg::load().expect("Failed to load init arguments"); + let mut res: BTreeMap = BTreeMap::new(); + + res.insert("One".into(), 1); + + msg::reply(res, 0).unwrap(); +} #[gstd::async_main] async fn main() { - gstd::exec::wait(); + let action: Action = msg::load().expect("Failed to load Action"); + + match action { + Action::One(_) => msg::send_with_gas( + msg::source(), + EmptyStruct { empty: () }, + 10000000, + 10_000_000_000_000, + ) + .unwrap(), + Action::Four() => { + let response: String = msg::send_for_reply_as(msg::source(), "reply", 0, 0) + .expect("Unable to send msg for reply") + .await + .expect("Error in async"); + msg::reply(response, 0).unwrap() + } + Action::Input(input) => { + if input != "Handle" { + panic!("Wrong input"); + } + + let response: InputStruct = msg::send_bytes_for_reply_as(msg::source(), b"PING", 0, 0) + .expect("Unable to send message for reply") + .await + .expect("Error in async"); + + if response.input != "Reply" { + panic!("Wrong input"); + } + msg::reply_bytes(b"ok", 0).unwrap() + } + Action::Wait() => { + gstd::exec::wait(); + } + _ => msg::reply("ok", 0).unwrap(), + }; } diff --git a/api/test/Message.test.ts b/api/test/Message.test.ts index 7f731c891c..febb9f8de0 100644 --- a/api/test/Message.test.ts +++ b/api/test/Message.test.ts @@ -2,9 +2,8 @@ import { HexString } from '@polkadot/util/types'; import { KeyringPair } from '@polkadot/keyring/types'; import { readFileSync } from 'fs'; -import { TEST_META, TEST_META_CODE } from './config'; -import { ProgramMetadata } from '../src'; -import { checkInit, getAccount, sendTransaction, sleep } from './utilsFunctions'; +import { TEST_CODE } from './config'; +import { checkInit, createPayload, getAccount, sendTransaction, sleep } from './utilsFunctions'; import { decodeAddress } from '../src/utils'; import { getApi } from './common'; @@ -13,9 +12,7 @@ let alice: KeyringPair; let programId: HexString; let messageToClaim: HexString; -const code = Uint8Array.from(readFileSync(TEST_META_CODE)); -const metaHex: HexString = `0x${readFileSync(TEST_META, 'utf-8')}`; -const metadata = ProgramMetadata.from(metaHex); +const code = Uint8Array.from(readFileSync(TEST_CODE)); beforeAll(async () => { await api.isReadyOrError; @@ -29,14 +26,11 @@ afterAll(async () => { describe('Gear Message', () => { test('upload test_meta', async () => { - programId = api.program.upload( - { - code, - initPayload: [1, 2, 3], - gasLimit: 200_000_000_000, - }, - metadata, - ).programId; + programId = api.program.upload({ + code, + initPayload: [1, 2, 3], + gasLimit: 200_000_000_000, + }).programId; const status = checkInit(api, programId); const [txData] = await sendTransaction(api.program, alice, ['MessageQueued']); expect(txData.destination.toHex()).toBe(programId); @@ -45,27 +39,22 @@ describe('Gear Message', () => { test('send messages', async () => { const messages = [ - { payload: { Two: [[8, 16]] }, reply: '0x086f6b', claim: true }, + { payload: createPayload('Action', { Two: [8, 16] }), reply: '0x086f6b', claim: true }, { - payload: { - One: 'Dmitriy', - }, + payload: createPayload('Action', { One: 'Dmitriy' }), value: 10_000_000_000_000, reply: '0x', }, ]; for (const message of messages) { - const tx = api.message.send( - { - destination: programId, - payload: message.payload, - gasLimit: 20_000_000_000, - value: message.value, - keepAlive: true, - }, - metadata, - ); + const tx = api.message.send({ + destination: programId, + payload: message.payload.toHex(), + gasLimit: 20_000_000_000, + value: message.value, + keepAlive: true, + }); const [txData, blockHash] = await sendTransaction(tx, alice, ['MessageQueued']); expect(txData).toBeDefined(); @@ -115,20 +104,17 @@ describe('Gear Message', () => { }); test('calculate reply', async () => { - const payload = { Two: [[8, 16]] }; + const payload = createPayload('Action', { Two: [8, 16] }).toHex(); const origin = decodeAddress(alice.address); - await api.program.calculateGas.handle(origin, programId, { Two: [[8, 16]] }, 0, false, metadata); + await api.program.calculateGas.handle(origin, programId, payload, 0, false); - const result = await api.message.calculateReply( - { - origin, - destination: programId, - payload, - }, - metadata, - ); + const result = await api.message.calculateReply({ + origin, + destination: programId, + payload, + }); const resultJson = result.toJSON(); diff --git a/api/test/Program.test.ts b/api/test/Program.test.ts index 138327b586..d1825be517 100644 --- a/api/test/Program.test.ts +++ b/api/test/Program.test.ts @@ -4,9 +4,8 @@ import { blake2AsHex } from '@polkadot/util-crypto'; import { bufferToU8a } from '@polkadot/util'; import { readFileSync } from 'fs'; -import { TEST_META, TEST_META_CODE } from './config'; -import { ProgramMetadata } from '../src'; -import { checkInit, getAccount, sendTransaction, sleep, waitForPausedProgram } from './utilsFunctions'; +import { TEST_CODE } from './config'; +import { checkInit, createPayload, getAccount, sendTransaction, sleep, waitForPausedProgram } from './utilsFunctions'; import { getApi } from './common'; const api = getApi(); @@ -18,8 +17,7 @@ let metaHash: HexString; let expiredBN: number; let pausedBlockHash: HexString; -const code = Uint8Array.from(readFileSync(TEST_META_CODE)); -const metaHex: HexString = `0x${readFileSync(TEST_META, 'utf-8')}`; +const code = Uint8Array.from(readFileSync(TEST_CODE)); beforeAll(async () => { await api.isReadyOrError; @@ -33,16 +31,11 @@ afterAll(async () => { describe('New Program', () => { test('Upload program', async () => { - const metadata = ProgramMetadata.from(metaHex); - - const program = api.program.upload( - { - code, - gasLimit: 200_000_000_000, - initPayload: [1, 2, 3], - }, - metadata, - ); + const program = api.program.upload({ + code, + gasLimit: 200_000_000_000, + initPayload: [1, 2, 3], + }); expect(program.programId).toBeDefined(); expect(program.salt).toBeDefined(); expect(program.codeId).toBeDefined(); @@ -77,7 +70,7 @@ describe('New Program', () => { expect(await status).toBe('success'); const reply = await api.message.getReplyEvent(programId, mqData.id.toHex(), blockHash); - expect(metadata.createType(metadata.types.init.output!, reply.data.message.payload).toJSON()).toMatchObject({ + expect(createPayload('Init', reply.data.message.payload).toJSON()).toMatchObject({ One: 1, }); expect(isProgramSetHappened).toBeTruthy(); @@ -93,17 +86,12 @@ describe('New Program', () => { test('Create program', async () => { expect(codeId).toBeDefined(); - const metadata = ProgramMetadata.from(metaHex); - - const { programId, salt } = api.program.create( - { - codeId, - gasLimit: 200_000_000_000, - initPayload: [4, 5, 6], - }, - metadata, - metadata.types.init.input, - ); + + const { programId, salt } = api.program.create({ + codeId, + gasLimit: 200_000_000_000, + initPayload: [4, 5, 6], + }); expect(programId).toBeDefined(); expect(salt).toBeDefined(); @@ -123,7 +111,7 @@ describe('New Program', () => { expect(programChangedStatuses).toContain('Active'); const reply = await api.message.getReplyEvent(programId, transactionData.id.toHex(), blockHash); - expect(metadata.createType(metadata.types.init.output!, reply.data.message.payload).toJSON()).toMatchObject({ + expect(createPayload('Init', reply.data.message.payload).toJSON()).toMatchObject({ One: 1, }); }); @@ -188,25 +176,25 @@ describe('Program', () => { expect(codeHash).toBe(codeId); }); - test('Get metahash by program id', async () => { - expect(programId).toBeDefined(); - metaHash = await api.program.metaHash(programId); - expect(metaHash).toBe(blake2AsHex(metaHex, 256)); - }); + // test('Get metahash by program id', async () => { + // expect(programId).toBeDefined(); + // metaHash = await api.program.metaHash(programId); + // expect(metaHash).toBe(blake2AsHex(metaHex, 256)); + // }); - test('Get metahash by codeId', async () => { + test.skip('Get metahash by codeId', async () => { expect(programId).toBeDefined(); expect(codeId).toBeDefined(); const codeMetaHash = await api.code.metaHash(codeId); expect(codeMetaHash).toBe(metaHash); }); - test('Get metahash by wasm', async () => { + test.skip('Get metahash by wasm', async () => { const codeMetaHash = await api.code.metaHashFromWasm(code); expect(codeMetaHash).toBe(metaHash); }); - test('Get metahash by wasm if it is Uint8Array', async () => { + test.skip('Get metahash by wasm if it is Uint8Array', async () => { const codeMetaHash = await api.code.metaHashFromWasm(bufferToU8a(code)); expect(codeMetaHash).toBe(metaHash); }); diff --git a/api/test/Voucher.test.ts b/api/test/Voucher.test.ts index 12bb7fcbb9..4c25c94f4c 100644 --- a/api/test/Voucher.test.ts +++ b/api/test/Voucher.test.ts @@ -3,9 +3,9 @@ import { KeyringPair } from '@polkadot/keyring/types'; import { join } from 'path'; import { readFileSync } from 'fs'; -import { TARGET, TEST_META, TEST_META_CODE } from './config'; -import { ProgramMetadata, decodeAddress } from '../src'; -import { checkInit, getAccount, sendTransaction, sleep } from './utilsFunctions'; +import { TARGET, TEST_CODE } from './config'; +import { decodeAddress } from '../src'; +import { checkInit, createPayload, getAccount, sendTransaction, sleep } from './utilsFunctions'; import { getApi } from './common'; let alice: KeyringPair; @@ -19,9 +19,7 @@ let voucher: string; let validUpTo: number; const api = getApi(); -const code = Uint8Array.from(readFileSync(TEST_META_CODE)); -const metaHex: HexString = `0x${readFileSync(TEST_META, 'utf-8')}`; -const metadata = ProgramMetadata.from(metaHex); +const code = Uint8Array.from(readFileSync(TEST_CODE)); beforeAll(async () => { await api.isReadyOrError; @@ -40,14 +38,11 @@ afterAll(async () => { describe('Voucher', () => { test('Upload test_meta program', async () => { - programId = api.program.upload( - { - code, - initPayload: [1, 2, 3], - gasLimit: 200_000_000_000, - }, - metadata, - ).programId; + programId = api.program.upload({ + code, + initPayload: [1, 2, 3], + gasLimit: 200_000_000_000, + }).programId; const status = checkInit(api, programId); const [txData] = await sendTransaction(api.program, alice, ['MessageQueued']); expect(txData.destination.toHex()).toBe(programId); @@ -71,21 +66,12 @@ describe('Voucher', () => { }); test.skip('Send msg with voucher (deprecated)', async () => { - const tx = api.message.send( - { - destination: programId, - payload: { - Four: { - array8: new Array(8).fill(0), - array32: new Array(32).fill(1), - actor: charlieRaw, - }, - }, - gasLimit: 20_000_000_000, - account: charlieRaw, - }, - metadata, - ); + const tx = api.message.send({ + destination: programId, + payload: createPayload('Action', { Four: null }).toHex(), + gasLimit: 20_000_000_000, + account: charlieRaw, + }); const [txData] = await sendTransaction(api.voucher.callDeprecated({ SendMessage: tx }), charlie, ['MessageQueued']); expect(txData).toBeDefined(); @@ -152,21 +138,12 @@ describe('Voucher', () => { test('Send msg with voucher', async () => { expect(voucher).toBeDefined(); - const tx = api.message.send( - { - destination: programId, - payload: { - Four: { - array8: new Array(8).fill(0), - array32: new Array(32).fill(1), - actor: charlieRaw, - }, - }, - gasLimit: 20_000_000_000, - account: charlieRaw, - }, - metadata, - ); + const tx = api.message.send({ + destination: programId, + payload: createPayload('Action', { Four: null }).toHex(), + gasLimit: 20_000_000_000, + account: charlieRaw, + }); const [txData] = await sendTransaction(api.voucher.call(voucher, { SendMessage: tx }), charlie, ['MessageQueued']); expect(txData).toBeDefined(); @@ -183,17 +160,13 @@ describe('Voucher', () => { const msgToReply = mailbox[0][0].id.toHex(); - const tx = await api.message.sendReply( - { - replyToId: msgToReply, - account: charlieRaw, - gasLimit: 20_000_000_000, - value: 0, - payload: { TextReply: 'Charlie' }, - }, - metadata, - metadata.types.reply!, - ); + const tx = await api.message.sendReply({ + replyToId: msgToReply, + account: charlieRaw, + gasLimit: 20_000_000_000, + value: 0, + payload: createPayload('ReplyType', { TextReply: 'Charlie' }).toHex(), + }); const [txData, blockHash] = await sendTransaction(api.voucher.call(voucher, { SendReply: tx }), charlie, [ 'MessageQueued', diff --git a/api/test/Waitlist.test.ts b/api/test/Waitlist.test.ts index e045e68be0..424b0c4904 100644 --- a/api/test/Waitlist.test.ts +++ b/api/test/Waitlist.test.ts @@ -3,7 +3,7 @@ import { KeyringPair } from '@polkadot/keyring/types'; import { CreateType, MessageWaitedData } from '../src'; import { TEST_CODE } from './config'; -import { checkInit, getAccount, listenToMessageWaited, sendTransaction, sleep } from './utilsFunctions'; +import { checkInit, createPayload, getAccount, listenToMessageWaited, sendTransaction, sleep } from './utilsFunctions'; import { readFileSync } from 'fs'; import { getApi } from './common'; @@ -18,7 +18,7 @@ beforeAll(async () => { await api.isReadyOrError; const code = Uint8Array.from(readFileSync(TEST_CODE)); alice = await getAccount('//Alice'); - programId = api.program.upload({ code, gasLimit: 20_000_000_000 }).programId; + programId = api.program.upload({ code, initPayload: [1, 2, 3], gasLimit: 20_000_000_000 }).programId; const init = checkInit(api, programId); await sendTransaction(api.program, alice, ['MessageQueued']); expect(await init).toBe('success'); @@ -32,7 +32,11 @@ afterAll(async () => { describe('GearWaitlist', () => { test("read program's waitlist", async () => { - await api.message.send({ destination: programId, payload: '0x00', gasLimit: 20_000_000_000 }); + await api.message.send({ + destination: programId, + payload: createPayload('Action', { Wait: null }).toHex(), + gasLimit: 20_000_000_000, + }); messageId = (await sendTransaction(api.message, alice, ['MessageQueued']))[0].id.toHex(); const eventData = await messageWaited(messageId); expect(eventData).toBeDefined(); @@ -63,7 +67,11 @@ describe('GearWaitlist', () => { }); test("send one more message and read program's waitlist", async () => { - await api.message.send({ destination: programId, payload: '0x00', gasLimit: 20_000_000_000 }); + await api.message.send({ + destination: programId, + payload: createPayload('Action', { Wait: null }).toHex(), + gasLimit: 20_000_000_000, + }); messageId = (await sendTransaction(api.message, alice, ['MessageQueued']))[0]; const waitlist = await api.waitlist.read(programId); expect(waitlist).toHaveLength(2); diff --git a/api/test/utilsFunctions.ts b/api/test/utilsFunctions.ts index d5bbf24885..9c98c4a6d9 100644 --- a/api/test/utilsFunctions.ts +++ b/api/test/utilsFunctions.ts @@ -5,6 +5,8 @@ import { KeyringPair } from '@polkadot/keyring/types'; import { GearApi, GearTransaction, IGearEvent, IGearVoucherEvent, MessageWaitedData, ProgramChangedData } from '../src'; import { Keyring } from '@polkadot/keyring'; import { waitReady } from '@polkadot/wasm-crypto'; +import { TypeRegistry } from '@polkadot/types'; +import { Codec } from '@polkadot/types-codec/types'; export const checkInit = ( api: GearApi, @@ -109,3 +111,34 @@ export const waitForPausedProgram = ( }); }); }; + +const registry = new TypeRegistry(); + +registry.register({ + Action: { + _enum: { + One: 'Option', + Two: '(u8, u16)', + Three: null, + Four: null, + Input: 'Text', + Wait: null, + }, + }, + Init: 'BTreeMap', + ReplyType: { + _enum: { + TextReply: 'Text', + }, + }, +}); + +export const createPayload = (type: string, data: unknown): Codec => { + const payload = registry.createType(type, data); + + if (!payload) { + throw new Error(`Type ${type} is not registered in the registry.`); + } + + return payload; +}; From 9fc640bc4af8bac52fd4b139fac607fe80e4ae47 Mon Sep 17 00:00:00 2001 From: Zewasik Date: Mon, 6 Jan 2025 11:25:08 +0200 Subject: [PATCH 2/2] remove unnecessary code --- api/programs/test/src/lib.rs | 1 - api/test/Program.test.ts | 6 ------ api/test/utilsFunctions.ts | 1 - 3 files changed, 8 deletions(-) diff --git a/api/programs/test/src/lib.rs b/api/programs/test/src/lib.rs index ed57efa9cf..6556ef28b7 100644 --- a/api/programs/test/src/lib.rs +++ b/api/programs/test/src/lib.rs @@ -11,7 +11,6 @@ use gstd::{ pub enum Action { One(Option), Two((u8, u16)), - Three(), Four(), Input(String), Wait(), diff --git a/api/test/Program.test.ts b/api/test/Program.test.ts index d1825be517..22b19c9493 100644 --- a/api/test/Program.test.ts +++ b/api/test/Program.test.ts @@ -176,12 +176,6 @@ describe('Program', () => { expect(codeHash).toBe(codeId); }); - // test('Get metahash by program id', async () => { - // expect(programId).toBeDefined(); - // metaHash = await api.program.metaHash(programId); - // expect(metaHash).toBe(blake2AsHex(metaHex, 256)); - // }); - test.skip('Get metahash by codeId', async () => { expect(programId).toBeDefined(); expect(codeId).toBeDefined(); diff --git a/api/test/utilsFunctions.ts b/api/test/utilsFunctions.ts index 9c98c4a6d9..0cd532194a 100644 --- a/api/test/utilsFunctions.ts +++ b/api/test/utilsFunctions.ts @@ -119,7 +119,6 @@ registry.register({ _enum: { One: 'Option', Two: '(u8, u16)', - Three: null, Four: null, Input: 'Text', Wait: null,