Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pink-system: Add api code_exists #1181

Merged
merged 1 commit into from
Mar 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion crates/pink-drivers/system/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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())
h4x3rotab marked this conversation as resolved.
Show resolved Hide resolved
}
}

impl ContractDeposit for System {
Expand Down
21 changes: 21 additions & 0 deletions crates/pink/pink-extension/src/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<T, E = Error> = core::result::Result<T, E>;

Expand Down Expand Up @@ -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.
Expand Down
30 changes: 20 additions & 10 deletions e2e/src/fullstack.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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 = `
Expand All @@ -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 } } }));
}

{
Expand All @@ -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 () {
Expand Down