Skip to content

Commit

Permalink
Merge pull request #60 from sporeprotocol/feat/change-payment-method
Browse files Browse the repository at this point in the history
feat: change payment from u8 to u64
  • Loading branch information
ashuralyk authored Mar 13, 2024
2 parents 6438102 + c83b005 commit 2e8763f
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 67 deletions.
37 changes: 2 additions & 35 deletions contracts/cluster/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,40 +25,6 @@ use spore_utils::{

use crate::hash::SPORE_EXTENSION_LUA;

#[allow(unused)]
fn process_input(
index: usize,
input_source: Source,
group_cell_in_outputs: &mut Vec<usize>,
output_source: Source,
) -> Result<(), Error> {
let group_id = load_cell_type(index, input_source)?
.unwrap_or_default()
.args();

for i in 0..group_cell_in_outputs.len() {
let output_index = group_cell_in_outputs.get(i).unwrap();
let output_group_id = load_cell_type(*output_index, output_source)?
.unwrap_or_default()
.args();

if group_id.as_slice()[..] == output_group_id.as_slice()[..] {
let group_data = load_cluster_data(index, input_source)?;
let output_group_data = load_cluster_data(i, output_source)?;

if group_data.name().as_slice()[..] != output_group_data.name().as_slice()[..] {
return Err(Error::ModifyClusterPermanentField);
}

group_cell_in_outputs.remove(i);
return Ok(());
}
}

// can not destroy a group cell now
Err(Error::InvalidClusterOperation)
}

fn load_cluster_data(index: usize, source: Source) -> Result<ClusterData, Error> {
let raw_data = load_cell_data(index, source)?;
let cluster_data = ClusterData::from_compatible_slice(raw_data.as_slice())
Expand Down Expand Up @@ -108,7 +74,8 @@ fn process_transfer() -> Result<(), Error> {
}

// check co-build action @lyk
let action::SporeActionUnion::TransferCluster(transfer) = extract_spore_action()?.to_enum() else {
let action::SporeActionUnion::TransferCluster(transfer) = extract_spore_action()?.to_enum()
else {
return Err(Error::SporeActionMismatch);
};
if transfer.cluster_id().as_slice() != &load_self_id()? {
Expand Down
25 changes: 15 additions & 10 deletions contracts/cluster_agent/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ use spore_types::generated::action;
use spore_utils::{
calc_capacity_sum, find_position_by_type, find_position_by_type_hash, load_self_id,
};
use spore_utils::{check_spore_address, extract_spore_action};

const CLUSTER_PROXY_ID_LEN: usize = 32;
use spore_utils::{
check_spore_address, extract_spore_action, CLUSTER_PROXY_ID_LEN,
CLUSTER_PROXY_ID_WITH_PAYMENT_LEN,
};

fn is_valid_cluster_proxy_cell(script_hash: &[u8; 32]) -> bool {
crate::hash::CLUSTER_PROXY_CODE_HASHES.contains(script_hash)
Expand Down Expand Up @@ -72,11 +73,12 @@ fn process_creation(_index: usize) -> Result<(), Error> {
.unwrap_or_default()
.args()
.raw_data();
if proxy_type_args.len() > CLUSTER_PROXY_ID_LEN {
let minimal_payment_args = proxy_type_args.get(CLUSTER_PROXY_ID_LEN).unwrap_or(&0);
debug!("Minimal payment is: {}", minimal_payment_args);
if proxy_type_args.len() == CLUSTER_PROXY_ID_WITH_PAYMENT_LEN {
let range = CLUSTER_PROXY_ID_LEN..CLUSTER_PROXY_ID_WITH_PAYMENT_LEN;
let minimal_payment =
u64::from_le_bytes(proxy_type_args[range].try_into().unwrap_or_default());
debug!("Minimal payment is: {}", minimal_payment);

let minimal_payment = 10u128.pow(*minimal_payment_args as u32);
let proxy_lock_hash = load_cell_lock_hash(proxy_index, CellDep)?;
let input_capacity = calc_capacity_sum(&proxy_lock_hash, Input);
let output_capacity = calc_capacity_sum(&proxy_lock_hash, Output);
Expand All @@ -89,7 +91,9 @@ fn process_creation(_index: usize) -> Result<(), Error> {
}
}
} else {
return Err(Error::PaymentMethodNotSupport);
if proxy_type_args.len() != CLUSTER_PROXY_ID_LEN {
return Err(Error::PaymentMethodNotSupport);
}
}
}

Expand All @@ -98,7 +102,7 @@ fn process_creation(_index: usize) -> Result<(), Error> {
return Err(Error::SporeActionMismatch);
};
if &cluster_id != mint.cluster_id().as_slice()
|| &proxy_type.args().raw_data()[..32] != mint.proxy_id().as_slice()
|| &proxy_type.args().raw_data()[..CLUSTER_PROXY_ID_LEN] != mint.proxy_id().as_slice()
{
return Err(Error::SporeActionFieldMismatch);
}
Expand All @@ -116,7 +120,8 @@ fn process_transfer() -> Result<(), Error> {
}

// co-build check @lyk
let action::SporeActionUnion::TransferAgent(transfer) = extract_spore_action()?.to_enum() else {
let action::SporeActionUnion::TransferAgent(transfer) = extract_spore_action()?.to_enum()
else {
return Err(Error::SporeActionMismatch);
};
if &load_self_id()? != transfer.cluster_id().as_slice() {
Expand Down
16 changes: 13 additions & 3 deletions contracts/cluster_proxy/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ use core::result::Result;
// Import from `core` instead of from `std` since we are in no-std mode
use ckb_std::ckb_constants::Source::{CellDep, GroupInput, GroupOutput, Input, Output};
use ckb_std::ckb_types::packed::Script;
use ckb_std::high_level::{load_cell_data, load_cell_lock_hash, load_cell_type, QueryIter};
use ckb_std::high_level::{
load_cell_data, load_cell_lock_hash, load_cell_type, load_script, QueryIter,
};

use spore_errors::error::Error;
use spore_types::generated::action;
use spore_utils::{
check_spore_address, extract_spore_action, find_position_by_lock_hash, find_position_by_type,
find_position_by_type_args, load_self_id, verify_type_id,
find_position_by_type_args, load_self_id, verify_type_id, CLUSTER_PROXY_ID_LEN,
CLUSTER_PROXY_ID_WITH_PAYMENT_LEN,
};

fn is_valid_cluster_cell(script_hash: &[u8; 32]) -> bool {
Expand All @@ -25,6 +28,12 @@ fn process_creation(index: usize) -> Result<(), Error> {
find_position_by_type_args(&cluster_id, CellDep, Some(is_valid_cluster_cell))
.ok_or(Error::ClusterCellNotInDep)?;

// verify script args format
let args = load_script()?.args().raw_data();
if args.len() != CLUSTER_PROXY_ID_LEN && args.len() != CLUSTER_PROXY_ID_WITH_PAYMENT_LEN {
return Err(Error::InvalidProxyArgs);
}

// verify Proxy ID
let Some(proxy_id) = verify_type_id(index) else {
return Err(Error::InvalidProxyID);
Expand Down Expand Up @@ -66,7 +75,8 @@ fn process_transfer() -> Result<(), Error> {
}

// co-build check @lyk
let action::SporeActionUnion::TransferProxy(transfer) = extract_spore_action()?.to_enum() else {
let action::SporeActionUnion::TransferProxy(transfer) = extract_spore_action()?.to_enum()
else {
return Err(Error::SporeActionMismatch);
};
if input_data.as_slice() != transfer.cluster_id().as_slice()
Expand Down
28 changes: 14 additions & 14 deletions contracts/spore/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use spore_types::generated::spore::SporeData;
use spore_utils::{
calc_capacity_sum, check_spore_address, compatible_load_cluster_data, extract_spore_action,
find_position_by_lock_hash, find_position_by_type, find_position_by_type_args, load_self_id,
verify_type_id, MIME,
verify_type_id, MIME, MUTANT_ID_LEN, MUTANT_ID_WITH_PAYMENT_LEN,
};

use crate::hash::{CLUSTER_AGENT_CODE_HASHES, CLUSTER_CODE_HASHES};
Expand Down Expand Up @@ -241,7 +241,7 @@ fn process_transfer() -> Result<(), Error> {
}

fn verify_extension(mime: &MIME, op: Operation, argv: Vec<u8>) -> Result<(), Error> {
let mut payment_map: BTreeMap<[u8; 32], u8> = BTreeMap::new();
let mut payment_map: BTreeMap<[u8; 32], u64> = BTreeMap::new();
let mut extension_hash = [0u8; 32];
for mutant_id in mime.mutants.iter() {
let mutant_index =
Expand Down Expand Up @@ -306,28 +306,28 @@ fn verify_extension(mime: &MIME, op: Operation, argv: Vec<u8>) -> Result<(), Err

fn check_payment(
mutant_index: usize,
payment_map: &mut BTreeMap<[u8; 32], u8>,
payment_map: &mut BTreeMap<[u8; 32], u64>,
) -> Result<(), Error> {
let mutant_type = load_cell_type(mutant_index, CellDep)?.unwrap_or_default();
let args = mutant_type.args().raw_data();
// CAUTION: only check 33 size pattern, leave room for user customization
if args.len() > 32 {
// CAUTION: only check bytes in [32, 40) pattern, leave room for user customization
if args.len() > MUTANT_ID_LEN {
if args.len() < MUTANT_ID_WITH_PAYMENT_LEN {
return Err(Error::InvalidExtensionPaymentFormat);
}
// we need a payment
let self_lock_hash = load_cell_lock_hash(0, GroupOutput)?;
let mutant_lock_hash = load_cell_lock_hash(mutant_index, CellDep)?;

let input_capacity = calc_capacity_sum(&self_lock_hash, Input);
let output_capacity = calc_capacity_sum(&mutant_lock_hash, Output);
let payment_power = {
let previous_power = payment_map.entry(mutant_lock_hash).or_default();
let current_power = args.get(32).cloned().unwrap_or(0);
let power = *previous_power + current_power;
*previous_power = power;
power
let minimal_payment = {
let range = MUTANT_ID_LEN..MUTANT_ID_WITH_PAYMENT_LEN;
let threshold = u64::from_le_bytes(args[range].try_into().unwrap_or_default());
let payment_threshold = payment_map.entry(mutant_lock_hash).or_default();
*payment_threshold += threshold;
*payment_threshold
};
let minimal_payment = 10u128.pow(payment_power as u32);

debug!("check mutant payment: {minimal_payment}");
if input_capacity + minimal_payment > output_capacity {
return Err(Error::ExtensionPaymentNotEnough);
}
Expand Down
2 changes: 2 additions & 0 deletions lib/errors/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub enum Error {
InvalidProxyOperation = 30,
ImmutableProxyFieldModification,
InvalidProxyID,
InvalidProxyArgs,

// cluster_agent errors
InvalidAgentOperation = 40,
Expand Down Expand Up @@ -69,6 +70,7 @@ pub enum Error {
ExtensionCellNotInDep,
ExtensionPaymentNotEnough,
ClusterRequiresMutantApplied,
InvalidExtensionPaymentFormat,

// mime errors
Illformed = 80,
Expand Down
10 changes: 8 additions & 2 deletions lib/utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ pub mod co_build_types {

mod mime;

pub const MUTANT_ID_LEN: usize = 32;
pub const MUTANT_ID_WITH_PAYMENT_LEN: usize = MUTANT_ID_LEN + 8;

pub const CLUSTER_PROXY_ID_LEN: usize = 32;
pub const CLUSTER_PROXY_ID_WITH_PAYMENT_LEN: usize = CLUSTER_PROXY_ID_LEN + 8;

pub fn load_self_id() -> Result<Vec<u8>, Error> {
Ok(load_script()?.args().raw_data()[..32].to_vec())
}
Expand Down Expand Up @@ -147,10 +153,10 @@ pub fn find_position_by_lock_hash(lock_hash: &[u8; 32], source: Source) -> Optio
QueryIter::new(load_cell_lock_hash, source).position(|hash| hash[..] == lock_hash[..])
}

pub fn calc_capacity_sum(lock_hash: &[u8; 32], source: Source) -> u128 {
pub fn calc_capacity_sum(lock_hash: &[u8; 32], source: Source) -> u64 {
QueryIter::new(load_cell, source)
.filter(|cell| cell.lock().calc_script_hash().raw_data().as_ref() == lock_hash)
.map(|cell| cell.capacity().unpack() as u128)
.map(|cell| cell.capacity().unpack())
.sum()
}

Expand Down
2 changes: 1 addition & 1 deletion tests/src/tests/cluster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ fn test_cluster_agent_mint() {
build_spore_type_script(&mut context, &agent_out_point, cluster_id.to_vec().into());
let agent_out_cell = build_normal_output_cell_with_type(&mut context, agent_type.clone())
.as_builder()
.capacity((UNIFORM_CAPACITY + 10).pack())
.capacity((2 * CAPACITY_UNIT).pack())
.build();

let tx = TransactionBuilder::default()
Expand Down
6 changes: 4 additions & 2 deletions tests/src/utils/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub mod co_build;
mod internal;

pub const UNIFORM_CAPACITY: u64 = 1000u64;
pub const CAPACITY_UNIT: u64 = 100_000_000;

pub fn build_serialized_cluster_data(name: &str, description: &str) -> ClusterData {
ClusterData::new_builder()
Expand Down Expand Up @@ -64,9 +65,10 @@ pub fn build_spore_type_script_with_payment(
context: &mut Context,
out_point: &OutPoint,
args: &[u8; 32],
payment: u8,
payment: u64,
) -> Option<Script> {
let args = vec![args.to_vec(), vec![payment]].concat();
let payment_in_ckb = payment * CAPACITY_UNIT;
let args = vec![args.to_vec(), payment_in_ckb.to_le_bytes().to_vec()].concat();
context.build_script_with_hash_type(out_point, ScriptHashType::Data1, args.into())
}

Expand Down

0 comments on commit 2e8763f

Please sign in to comment.