From 63e791c47d75a99424ca4c3fed7d1fc06e2f351b Mon Sep 17 00:00:00 2001 From: Kevin Wang Date: Tue, 28 Feb 2023 10:11:35 +0000 Subject: [PATCH] pink-system: Add api code_exists --- crates/pink-drivers/system/lib.rs | 8 ++++++- crates/pink/pink-extension/src/system.rs | 21 +++++++++++++++++ e2e/src/fullstack.js | 30 ++++++++++++++++-------- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/crates/pink-drivers/system/lib.rs b/crates/pink-drivers/system/lib.rs index 4d4e7b3cc4..ecdf3d3729 100755 --- a/crates/pink-drivers/system/lib.rs +++ b/crates/pink-drivers/system/lib.rs @@ -11,7 +11,7 @@ mod system { use super::pink; use alloc::string::String; use ink::{codegen::Env, storage::Mapping}; - use pink::system::{ContractDeposit, ContractDepositRef, DriverError, Error, Result}; + use pink::system::{CodeType, ContractDeposit, ContractDepositRef, DriverError, Error, Result}; use pink::{HookPoint, PinkEnvironment}; /// Pink's system contract. @@ -209,6 +209,12 @@ mod system { pink::upgrade_runtime(version); Ok(()) } + + /// Check if the code is already uploaded to the cluster with given code hash. + #[ink(message)] + fn code_exists(&self, code_hash: [u8; 32], code_type: CodeType) -> bool { + pink::ext().code_exists(code_hash.into(), code_type.is_sidevm()) + } } impl ContractDeposit for System { diff --git a/crates/pink/pink-extension/src/system.rs b/crates/pink/pink-extension/src/system.rs index c9623f70e0..f755dd893b 100644 --- a/crates/pink/pink-extension/src/system.rs +++ b/crates/pink/pink-extension/src/system.rs @@ -17,6 +17,23 @@ pub enum Error { ConditionNotMet, } +/// The code type for existance check. +#[derive(Debug, PartialEq, Eq, Encode, Decode)] +#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] +pub enum CodeType { + Ink, + Sidevm, +} + +impl CodeType { + pub fn is_ink(&self) -> bool { + matches!(self, CodeType::Ink) + } + pub fn is_sidevm(&self) -> bool { + matches!(self, CodeType::Sidevm) + } +} + /// Result type for the system contract messages pub type Result = core::result::Result; @@ -103,6 +120,10 @@ pub trait System { /// Upgrade the contract runtime #[ink(message)] fn upgrade_runtime(&self, version: (u32, u32)) -> Result<()>; + + /// Check if the code is already uploaded to the cluster with given code hash. + #[ink(message)] + fn code_exists(&self, code_hash: Hash, code_type: CodeType) -> bool; } /// Errors that can occur upon calling a driver contract. diff --git a/e2e/src/fullstack.js b/e2e/src/fullstack.js index 0d8cfe0139..d64c4317d6 100644 --- a/e2e/src/fullstack.js +++ b/e2e/src/fullstack.js @@ -558,12 +558,18 @@ describe('A full stack', function () { it('can upload code with access control', async function () { const code = hex(contract.wasm); - // For now, there is no way to check whether code is uploaded in script - // since this requires monitering the async CodeUploaded event + const codeHash = hex(contract.hash); + await assert.txAccepted( api.tx.phalaFatContracts.clusterUploadResource(clusterId, 'InkCode', hex(code)), alice, ); + + assert.isTrue(await checkUntil(async () => { + const { output } = await ContractSystem.query['system::codeExists'](certAlice, {}, codeHash, 'Ink'); + return output?.eq({ Ok: true }) + }, 4 * 6000), 'Upload system checker code failed'); + await assert.txFailed( api.tx.phalaFatContracts.clusterUploadResource(clusterId, 'InkCode', hex(code)), bob, @@ -638,6 +644,10 @@ describe('A full stack', function () { api.tx.phalaFatContracts.clusterUploadResource(clusterId, 'IndeterministicInkCode', hex(code)), alice, ); + assert.isTrue(await checkUntil(async () => { + const { output } = await ContractSystem.query['system::codeExists'](certAlice, {}, codeHash, 'Ink'); + return output?.eq({ Ok: true }) + }, 4 * 6000), 'Upload qjs code failed'); { // args works const jsCode = ` @@ -646,11 +656,9 @@ describe('A full stack', function () { return scriptArgs[0]; })() `; - assert.isTrue(await checkUntil(async () => { - const arg0 = "Powered by QuickJS in ink!"; - const { output } = await ContractSystemChecker.query.evalJs(certAlice, {}, codeHash, jsCode, [arg0]); - return output?.eq({ Ok: { Ok: { String: arg0 } } }); - }, 4 * 6000), 'Failed to evaluate js in contract'); + const arg0 = "Powered by QuickJS in ink!"; + const { output } = await ContractSystemChecker.query.evalJs(certAlice, {}, codeHash, jsCode, [arg0]); + assert.isTrue(output?.eq({ Ok: { Ok: { String: arg0 } } })); } { @@ -672,9 +680,11 @@ describe('A full stack', function () { alice, ); assert.isTrue(await checkUntil(async () => { - const { output } = await ContractSystemChecker.query.parseUsd(certAlice, {}, codeHash, '{"usd":1.23}'); - return output?.asOk.unwrap()?.usd.eq(123); - }, 4 * 6000), 'Failed to parse json in contract'); + const { output } = await ContractSystem.query['system::codeExists'](certAlice, {}, codeHash, 'Ink'); + return output?.eq({ Ok: true }) + }, 4 * 6000), 'Upload test contract code failed'); + const { output } = await ContractSystemChecker.query.parseUsd(certAlice, {}, codeHash, '{"usd":1.23}'); + assert.isTrue(output?.asOk.unwrap()?.usd.eq(123)); }); it('tokenomic driver works', async function () {