Skip to content

Commit

Permalink
feat: change action.mol and enable co-build check in Cluster
Browse files Browse the repository at this point in the history
  • Loading branch information
liyukun committed Jan 6, 2024
1 parent 9308e77 commit d064145
Show file tree
Hide file tree
Showing 12 changed files with 1,559 additions and 786 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 29 additions & 3 deletions contracts/cluster/src/entry.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Import heap related library from `alloc`
// https://doc.rust-lang.org/alloc/index.html
use alloc::vec::Vec;
use ckb_std::ckb_types::util::hash::blake2b_256;
use spore_types::generated::action;
// Import from `core` instead of from `std` since we are in no-std mode
use core::result::Result;

Expand All @@ -16,7 +18,10 @@ use ckb_std::{
use ckb_std::high_level::{load_script, QueryIter};
use spore_errors::error::Error;
use spore_types::generated::spore_types::ClusterData;
use spore_utils::{find_position_by_type, find_position_by_type_args, verify_type_id};
use spore_utils::{
check_spore_address, extract_spore_action, find_position_by_type, find_position_by_type_args,
load_type_args, verify_type_id,
};

use crate::hash::SPORE_EXTENSION_LUA;

Expand Down Expand Up @@ -66,9 +71,9 @@ fn process_creation(index: usize) -> Result<(), Error> {
if cluster_data.name().is_empty() {
return Err(Error::EmptyName);
}
if verify_type_id(index, Output).is_none() {
let Some(cluster_id) = verify_type_id(index, Output) else {
return Err(Error::InvalidClusterID);
}
};

// Verify if mutant is set
if cluster_data.mutant_id().is_some() {
Expand All @@ -79,6 +84,17 @@ fn process_creation(index: usize) -> Result<(), Error> {
.ok_or(Error::MutantNotInDeps)?;
}

// check co-build action @lyk
let action::SporeActionUnion::ClusterCreate(create) = extract_spore_action()?.to_enum() else {
return Err(Error::SporeActionMismatch);
};
if cluster_id != create.cluster_id().as_slice()
|| blake2b_256(cluster_data.as_slice()) != create.data_hash().as_slice()
{
return Err(Error::SporeActionFieldMismatch);
}
check_spore_address(GroupOutput, create.to())?;

Ok(())
}

Expand All @@ -91,6 +107,16 @@ fn process_transfer() -> Result<(), Error> {
return Err(Error::ModifyClusterPermanentField);
}

// check co-build action @lyk
let action::SporeActionUnion::ClusterTransfer(transfer) = extract_spore_action()?.to_enum() else {
return Err(Error::SporeActionMismatch);
};
if transfer.cluster_id().as_slice() != load_type_args(0, GroupInput).as_ref() {
return Err(Error::SporeActionFieldMismatch);
}
check_spore_address(GroupInput, transfer.from())?;
check_spore_address(GroupOutput, transfer.to())?;

Ok(())
}

Expand Down
60 changes: 17 additions & 43 deletions contracts/spore/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ use core::result::Result;
use ckb_std::ckb_constants::Source::{CellDep, GroupInput, GroupOutput, Input, Output};
use ckb_std::ckb_types::core::ScriptHashType;
use ckb_std::ckb_types::packed::Script;
use ckb_std::high_level::{load_cell_data_hash, load_cell_lock_hash, load_script_hash};
use ckb_std::high_level::{load_cell_data_hash, load_cell_lock_hash};
use ckb_std::{
ckb_constants::Source,
ckb_types::prelude::*,
high_level::{load_cell_data, load_cell_type, QueryIter},
};

use spore_errors::error::Error;
use spore_types::generated::action;
use spore_types::generated::spore_types::{ClusterData, SporeData};
use spore_utils::{
calc_capacity_sum, find_position_by_lock_hash, find_position_by_type,
find_position_by_type_args, load_type_args, verify_type_id, MIME,
calc_capacity_sum, check_spore_address, extract_spore_action, find_position_by_lock_hash,
find_position_by_type, find_position_by_type_args, load_type_args, verify_type_id, MIME,
};

use crate::hash::{CLUSTER_AGENT_CODE_HASHES, CLUSTER_CODE_HASHES};
use crate::schema;

fn load_spore_data(index: usize, source: Source) -> Result<SporeData, Error> {
let raw_data = load_cell_data(index, source)?;
Expand All @@ -30,20 +30,7 @@ fn load_spore_data(index: usize, source: Source) -> Result<SporeData, Error> {
Ok(spore_data)
}

fn check_spore_address(
gourp_source: Source,
spore_address: Option<schema::Address>,
) -> Result<(), Error> {
if let Some(expected_address) = spore_address {
let address = load_cell_lock_hash(0, gourp_source)?;
if address.as_slice() != expected_address.as_slice() {
return Err(Error::SporeActionFieldMismatch);
}
}
Ok(())
}

fn process_creation(index: usize, action: schema::SporeAction) -> Result<(), Error> {
fn process_creation(index: usize) -> Result<(), Error> {
let spore_data = load_spore_data(index, Output)?;

if spore_data.content().is_empty() {
Expand Down Expand Up @@ -147,20 +134,20 @@ fn process_creation(index: usize, action: schema::SporeAction) -> Result<(), Err
}

// check co-build action @lyk
let schema::SporeActionUnion::Mint(mint) = action.to_enum() else {
let action::SporeActionUnion::Mint(mint) = extract_spore_action()?.to_enum() else {
return Err(Error::SporeActionMismatch);
};
if mint.nft_id().as_slice() != spore_id
|| mint.data_hash().as_slice() != blake2b_256(spore_data.as_slice())
{
return Err(Error::SporeActionFieldMismatch);
}
check_spore_address(GroupOutput, mint.to().to_opt())?;
check_spore_address(GroupOutput, mint.to())?;

Ok(())
}

fn process_destruction(action: schema::SporeAction) -> Result<(), Error> {
fn process_destruction() -> Result<(), Error> {
//destruction
let spore_data = load_spore_data(0, GroupInput)?;

Expand All @@ -179,18 +166,18 @@ fn process_destruction(action: schema::SporeAction) -> Result<(), Error> {
}

// check co-build action @lyk
let schema::SporeActionUnion::Burn(burn) = action.to_enum() else {
let action::SporeActionUnion::Burn(burn) = extract_spore_action()?.to_enum() else {
return Err(Error::SporeActionMismatch);
};
if burn.nft_id().as_slice() != load_type_args(0, GroupInput).as_ref() {
return Err(Error::SporeActionFieldMismatch);
}
check_spore_address(GroupInput, burn.from().to_opt())?;
check_spore_address(GroupInput, burn.from())?;

Ok(())
}

fn process_transfer(action: schema::SporeAction) -> Result<(), Error> {
fn process_transfer() -> Result<(), Error> {
// found same NFT in output, this is a transfer
// check no field was modified
let input_data = load_spore_data(0, GroupInput)?;
Expand All @@ -214,14 +201,14 @@ fn process_transfer(action: schema::SporeAction) -> Result<(), Error> {
}

// check co-build action @lyk
let schema::SporeActionUnion::Transfer(transfer) = action.to_enum() else {
let action::SporeActionUnion::Transfer(transfer) = extract_spore_action()?.to_enum() else {
return Err(Error::SporeActionMismatch);
};
if transfer.nft_id().as_slice() != load_type_args(0, GroupInput).as_ref() {
return Err(Error::SporeActionFieldMismatch);
}
check_spore_address(GroupInput, transfer.to().to_opt())?;
check_spore_address(GroupOutput, transfer.from().to_opt())?;
check_spore_address(GroupInput, transfer.to())?;
check_spore_address(GroupOutput, transfer.from())?;

Ok(())
}
Expand Down Expand Up @@ -313,31 +300,18 @@ pub fn main() -> Result<(), Error> {
return Err(Error::MultipleSpend);
}

let message = ckb_transaction_cobuild::fetch_message()
.map_err(|_| Error::InvliadCoBuildWitnessLayout)?
.ok_or(Error::InvliadCoBuildWitnessLayout)?;

let script_hash = load_script_hash()?;
let action = message
.actions()
.into_iter()
.find(|v| v.script_hash().as_slice() == script_hash.as_slice())
.ok_or(Error::InvliadCoBuildMessage)?;
let spore_action = schema::SporeAction::from_slice(&action.data().raw_data())
.map_err(|_| Error::InvliadCoBuildMessage)?;

match (spore_in_input.len(), spore_in_output.len()) {
(0, 1) => {
// find it's index in Output
let output_index =
find_position_by_type(&spore_in_output[0], Output).unwrap_or_default(); // Once we entered here, it can't be empty, and use 0 as a fallback position
return process_creation(output_index, spore_action);
return process_creation(output_index);
}
(1, 0) => {
return process_destruction(spore_action);
return process_destruction();
}
(1, 1) => {
return process_transfer(spore_action);
return process_transfer();
}
_ => unreachable!(),
}
Expand Down
1 change: 0 additions & 1 deletion contracts/spore/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
// define modules
mod entry;
mod hash;
mod schema;

#[cfg(test)]
extern crate alloc;
Expand Down
26 changes: 0 additions & 26 deletions contracts/spore/src/schema/action.mol

This file was deleted.

3 changes: 0 additions & 3 deletions contracts/spore/src/schema/mod.rs

This file was deleted.

10 changes: 5 additions & 5 deletions lib/errors/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ pub enum Error {
// common
ClusterCellNotInDep,
ClusterOwnershipVerifyFailed,
InvliadCoBuildWitnessLayout,
InvliadCoBuildMessage,
SporeActionMismatch,
SporeActionFieldMismatch,

// spore_extension_lua errors
ModifyExtensionPermanentField = 10,
ModifyExtensionPermanentField = 15,
ConflictExtensionCreation,
ExtensionMultipleSpend,
InvalidExtensionOperation,
Expand Down Expand Up @@ -61,10 +65,6 @@ pub enum Error {
ExtensionCellNotInDep,
ExtensionPaymentNotEnough,
ClusterRequiresMutantApplied,
InvliadCoBuildWitnessLayout,
InvliadCoBuildMessage,
SporeActionMismatch,
SporeActionFieldMismatch,

// mime errors
Illformed = 80,
Expand Down
56 changes: 56 additions & 0 deletions lib/types/schemas/action.mol
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
array Byte32 [byte; 32];
vector Bytes <byte>;

table Script {
code_hash: Byte32,
hash_type: byte,
args: Bytes,
}

union Address {
Script,
}

/* Actions for Spore */

table Mint {
nft_id: Byte32,
to: Address,
data_hash: Byte32,
}

table Transfer {
nft_id: Byte32,
from: Address,
to: Address,
}

table Burn {
nft_id: Byte32,
from: Address,
}

/* Actions for Cluster */

table ClusterCreate {
cluster_id: Byte32,
to: Address,
data_hash: Byte32,
}

table ClusterTransfer {
cluster_id: Byte32,
from: Address,
to: Address,
}

/* Action in ScriptInfo */

union SporeAction {
Mint,
Transfer,
Burn,

ClusterCreate,
ClusterTransfer,
}
Loading

0 comments on commit d064145

Please sign in to comment.