Skip to content
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
1 change: 1 addition & 0 deletions common/src/traits/tx_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ where
kicker_key: PrivateKey,
ckb: CkbNetwork<C>,
type_ids: CheckpointTypeIds,
epoch_len: u64,
new_checkpoint: Checkpoint,
) -> Self;

Expand Down
16 changes: 8 additions & 8 deletions common/src/types/tx_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ pub struct StakeItem {
pub inauguration_epoch: Epoch,
}

impl From<&StakeItem> for StakeInfoDelta {
fn from(stake: &StakeItem) -> Self {
impl From<StakeItem> for StakeInfoDelta {
fn from(stake: StakeItem) -> Self {
StakeInfoDelta::new_builder()
.is_increase(Byte::new(stake.is_increase.into()))
.amount(to_uint128(stake.amount))
Expand Down Expand Up @@ -111,8 +111,8 @@ impl DelegateItem {
}
}

impl From<&DelegateItem> for DelegateInfoDelta {
fn from(delegate: &DelegateItem) -> Self {
impl From<DelegateItem> for DelegateInfoDelta {
fn from(delegate: DelegateItem) -> Self {
DelegateInfoDelta::new_builder()
.staker(Identity::new_unchecked(
delegate.staker.as_bytes().to_owned().into(),
Expand All @@ -125,7 +125,7 @@ impl From<&DelegateItem> for DelegateInfoDelta {
}
}

#[derive(Default)]
#[derive(Default, Clone)]
pub struct Checkpoint {
pub epoch: Epoch,
pub period: u32,
Expand All @@ -137,8 +137,8 @@ pub struct Checkpoint {
pub propose_count: Vec<ProposeCount>,
}

impl From<&Checkpoint> for CheckpointCellData {
fn from(checkpoint: &Checkpoint) -> Self {
impl From<Checkpoint> for CheckpointCellData {
fn from(checkpoint: Checkpoint) -> Self {
CheckpointCellData::new_builder()
.version(Byte::default())
.epoch(to_uint64(checkpoint.epoch))
Expand All @@ -160,7 +160,7 @@ pub fn propose_counts(proposes: &[ProposeCount]) -> ProposeCounts {
propose_count.build()
}

#[derive(Default)]
#[derive(Default, Clone)]
pub struct Proof {
pub number: u64,
pub round: u64,
Expand Down
16 changes: 8 additions & 8 deletions devtools/tx-tests/src/config/type_ids.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
selection_type_id = "0x67c75bb2759250649b097b4251315758b4ee03508acb4f284bc33e0dd914c5d7"
issue_type_id = "0xf033654bfed1833c031340f8c94f17e6dd5564a412117be60dac5b2ef6d438a4"
checkpoint_type_id = "0x65b0165752ae44e18be4f722857c695bfe38986e740de8003703dd8c34916120"
metadata_type_id = "0x626e1e688278f6db98a1ce2d44d186e18c43c9b781d33225333a1062401bec0d"
stake_smt_type_id = "0xdb58fc7a64eae103975fe88567bd532a051d7732ee0faeb51a5497ac3ddf75df"
delegate_smt_type_id = "0x778f21066818394dc3f1d46562cc0bc145bd43bbf45f0a36b9aa092efa3542b4"
reward_smt_type_id = "0x41085040c66d8bc910a9780ad83472385e7cb03dd0c574dd3a5eab689ceffb8e"
xudt_owner = "0x7ab05e531ae8f970f227f334010f67d9a74ee9f7e902920185c709c63fc7d416"
selection_type_id = "0x705d8dc9b7cd351e29bfb24fb4443e0f7f40b01b13940db5a6f54adfa7b63170"
issue_type_id = "0x3054fe87c40f2ef563bb83e868bab744a173fe37a651d0448116a684e33650d5"
checkpoint_type_id = "0xf451af07b7771925065b3010362c5103cc1809a60de8fc2c9c82d2bec3404d0c"
metadata_type_id = "0xc5387cff490467c52bd2b2352c152a6aa57bbf469e4aa5fe51459ed0647c14c6"
stake_smt_type_id = "0x9b95a2923c775ab42e71314a3110614e86e051fd9c05186f0b0c335fd91e4630"
delegate_smt_type_id = "0xcba604590a06ccc77db8dd827516cb8dbddce2e176cc7ba36d7b4a40dd6b49a9"
reward_smt_type_id = "0x64ec42c5d6de37fc37ed337727ab73c54fef46204cba58bf4b923986b4aef858"
xudt_owner = "0x5bcdd4abdbc6b06a0e949bb469cc6d35e11c443fc9ab0586d5a937c662044964"
12 changes: 12 additions & 0 deletions devtools/tx-tests/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,21 @@ async fn main() {
.num_args(1)
.default_value("")
.help("test delegate tx"),
)
.arg(
clap::Arg::new("checkpoint")
.short('c')
.required(false)
.num_args(0)
.help("test checkpoint tx"),
);

let matches = cmd.get_matches();
let init = matches.get_one::<bool>("init").unwrap().to_owned();
let mint = matches.get_one::<bool>("mint").unwrap().to_owned();
let stake = matches.get_one::<String>("stake").unwrap().as_str();
let delegate = matches.get_one::<String>("delegate").unwrap().as_str();
let checkpoint = matches.get_one::<bool>("checkpoint").unwrap().to_owned();

let ckb = CkbNetwork {
network_type: NetworkType::Testnet,
Expand Down Expand Up @@ -80,4 +88,8 @@ async fn main() {
_ => unimplemented!(),
}
}

if checkpoint {
checkpoint_tx(ckb.clone()).await;
}
}
66 changes: 66 additions & 0 deletions devtools/tx-tests/src/tx/checkpoint.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use ckb_sdk::unlock::ScriptSigner;
use common::traits::tx_builder::ICheckpointTxBuilder;
use common::types::tx_builder::{Checkpoint, CheckpointTypeIds, CkbNetwork};
use rpc_client::ckb_client::ckb_rpc_client::CkbRpcClient;
use tx_builder::ckb::checkpoint::CheckpointTxBuilder;
use tx_builder::ckb::utils::omni::{omni_eth_ckb_address, omni_eth_signer};
use tx_builder::ckb::utils::tx::{gen_script_group, send_tx};

use crate::config::parse_file;
use crate::config::types::{PrivKeys, TypeIds as CTypeIds};
use crate::{PRIV_KEYS_PATH, TYPE_IDS_PATH};

pub async fn checkpoint_tx(ckb: CkbNetwork<CkbRpcClient>) {
let priv_keys: PrivKeys = parse_file(PRIV_KEYS_PATH);
let test_kicker_key = priv_keys.staker_privkeys[0].clone().into_h256().unwrap();
println!(
"kicker ckb addres: {}\n",
omni_eth_ckb_address(&ckb.network_type, test_kicker_key.clone()).unwrap()
);

let type_ids: CTypeIds = parse_file(TYPE_IDS_PATH);
let metadata_type_id = type_ids.metadata_type_id.into_h256().unwrap();
let checkpoint_type_id = type_ids.checkpoint_type_id.into_h256().unwrap();

let mut tx = CheckpointTxBuilder::new(
test_kicker_key.clone(),
ckb.clone(),
CheckpointTypeIds {
metadata_type_id,
checkpoint_type_id,
},
2,
Checkpoint {
epoch: 1,
period: 1,
latest_block_height: 10,
timestamp: 11111,
..Default::default()
},
)
.await
.build_tx()
.await
.unwrap();

let signer = omni_eth_signer(test_kicker_key).unwrap();
let script_groups = gen_script_group(&ckb.client, &tx).await.unwrap();
let mut first_group = true;

for group in script_groups.lock_groups.iter() {
if !first_group {
println!("sign; not checkpoint id: {:?}", group.1.input_indices);
tx = signer.sign_tx(&tx, group.1).unwrap();
} else {
println!("not sign; checkpoint id: {:?}", group.1.input_indices);
}
first_group = false;
}

match send_tx(&ckb.client, &tx.data().into()).await {
Ok(tx_hash) => println!("tx hash: 0x{}", tx_hash),
Err(e) => println!("{}", e),
}

println!("\ntx: {}", tx);
}
8 changes: 5 additions & 3 deletions devtools/tx-tests/src/tx/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ pub async fn init_tx(ckb: CkbNetwork<CkbRpcClient>) {
Checkpoint {
epoch: 0,
period: 0,
latest_block_height: 10,
timestamp: 11111,
..Default::default()
},
Metadata {
epoch_len: 2,
period_len: 2,
quorum: 2,
epoch_len: 100,
period_len: 100,
quorum: 10,
..Default::default()
},
)
Expand Down
2 changes: 2 additions & 0 deletions devtools/tx-tests/src/tx/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
mod checkpoint;
mod delegate;
mod init;
mod mint;
mod stake;

pub use checkpoint::checkpoint_tx;
pub use delegate::{add_delegate_tx, first_delegate_tx, reedem_delegate_tx};
pub use init::init_tx;
pub use mint::mint_tx;
Expand Down
102 changes: 54 additions & 48 deletions tx-builder/src/ckb/checkpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@ use bytes::Bytes;
use ckb_sdk::{unlock::ScriptSigner, ScriptGroup, ScriptGroupType};
use ckb_types::{
core::{Capacity, TransactionBuilder, TransactionView},
packed::{CellInput, CellOutput, Script},
packed::{CellInput, CellOutput},
prelude::{Entity, Pack},
};
use common::{
traits::{ckb_rpc_client::CkbRpc, tx_builder::ICheckpointTxBuilder},
types::{
ckb_rpc_client::Cell,
tx_builder::{CheckpointTypeIds, CkbNetwork},
},
types::tx_builder::{CheckpointTypeIds, CkbNetwork},
};
use common::{
types::tx_builder::{Checkpoint, PrivateKey},
Expand All @@ -25,7 +22,10 @@ use crate::ckb::{
define::error::CkbTxErr,
utils::{
cell_collector::get_unique_cell,
cell_dep::{metadata_cell_dep, omni_lock_dep, secp256k1_lock_dep, xudt_type_dep},
cell_dep::{
always_success_lock_dep, checkpoint_type_dep, metadata_cell_dep, omni_lock_dep,
secp256k1_lock_dep, xudt_type_dep,
},
omni::{omni_eth_address, omni_eth_signer, omni_eth_witness_placeholder},
script::{always_success_lock, checkpoint_type, omni_eth_lock},
tx::balance_tx,
Expand All @@ -36,11 +36,11 @@ pub struct CheckpointTxBuilder<C>
where
C: CkbRpc,
{
kicker_key: PrivateKey,
ckb: CkbNetwork<C>,
type_ids: CheckpointTypeIds,
new_checkpoint: Checkpoint,
checkpoint_type_script: Script,
kicker_key: PrivateKey,
ckb: CkbNetwork<C>,
type_ids: CheckpointTypeIds,
epoch_len: u64,
new_checkpoint: Checkpoint,
}

#[async_trait]
Expand All @@ -52,44 +52,61 @@ where
kicker_key: PrivateKey,
ckb: CkbNetwork<C>,
type_ids: CheckpointTypeIds,
epoch_len: u64,
new_checkpoint: Checkpoint,
) -> Self {
let checkpoint_type_script =
checkpoint_type(&ckb.network_type, &type_ids.checkpoint_type_id);
Self {
kicker_key,
ckb,
type_ids,
epoch_len,
new_checkpoint,
checkpoint_type_script,
}
}

async fn build_tx(&self) -> Result<TransactionView> {
let checkpoint_type =
checkpoint_type(&self.ckb.network_type, &self.type_ids.checkpoint_type_id);

let last_checkpoint_cell =
get_unique_cell(&self.ckb.client, self.checkpoint_type_script.clone()).await?;
self.check_occasion(last_checkpoint_cell.clone()).await?;
get_unique_cell(&self.ckb.client, checkpoint_type.clone()).await?;

let last_checkpoint_data = CheckpointCellData::new_unchecked(
last_checkpoint_cell.output_data.unwrap().into_bytes(),
);

self.check_occasion(
to_u64(&last_checkpoint_data.epoch()),
to_u32(&last_checkpoint_data.period()),
)
.await?;

let inputs: Vec<ckb_types::packed::CellInput> = vec![CellInput::new_builder()
.previous_output(last_checkpoint_cell.out_point.into())
.build()];

let new_checkpoint_data: CheckpointCellData = (&self.new_checkpoint).into();
let outputs_data = vec![new_checkpoint_data.as_bytes()];
let new_checkpoint_data: CheckpointCellData = self.new_checkpoint.clone().into();
let outputs_data = vec![new_checkpoint_data
.as_builder()
.metadata_type_id(last_checkpoint_data.metadata_type_id()) // metdata type script hash
.build()
.as_bytes()];

let outputs = vec![CellOutput::new_builder()
.lock(always_success_lock(&self.ckb.network_type))
.type_(Some(self.checkpoint_type_script.clone()).pack())
.type_(Some(checkpoint_type).pack())
.build_exact_capacity(Capacity::bytes(outputs_data[0].len())?)?];

let cell_deps = vec![
omni_lock_dep(&self.ckb.network_type),
secp256k1_lock_dep(&self.ckb.network_type),
xudt_type_dep(&self.ckb.network_type),
always_success_lock_dep(&self.ckb.network_type),
checkpoint_type_dep(&self.ckb.network_type),
metadata_cell_dep(
&self.ckb.client,
&self.ckb.network_type,
&self.type_ids.metadata_type_id,
&self.type_ids.metadata_type_id, // metadata type script args
)
.await?,
];
Expand All @@ -115,7 +132,6 @@ where
let tx = balance_tx(&self.ckb.client, kick_lock.clone(), tx).await?;

let signer = omni_eth_signer(self.kicker_key.clone())?;

let tx_view = signer.sign_tx(&tx, &ScriptGroup {
script: kick_lock,
group_type: ScriptGroupType::Lock,
Expand All @@ -131,39 +147,29 @@ impl<C> CheckpointTxBuilder<C>
where
C: CkbRpc,
{
async fn check_occasion(&self, last_checkpoint_cell: Cell) -> Result<(), CkbTxErr> {
let last_checkpoint_cell_data = CheckpointCellData::new_unchecked(
last_checkpoint_cell.output_data.unwrap().into_bytes(),
);
let last_epoch = to_u64(&last_checkpoint_cell_data.epoch());
let last_period = to_u32(&last_checkpoint_cell_data.period());
match self.new_checkpoint.epoch {
latest_epoch if latest_epoch == last_epoch.saturating_add(1) => {
match self.new_checkpoint.period {
0 => Ok(()),
_ => Err(CkbTxErr::NotCheckpointOccasion {
current_epoch: last_epoch,
current_period: last_period,
recorded_epoch: latest_epoch,
recorded_period: self.new_checkpoint.period,
}),
}
}
latest_epoch if latest_epoch == last_epoch => match self.new_checkpoint.period {
last_period if last_period == last_period.saturating_add(1) => Ok(()),
_ => Err(CkbTxErr::NotCheckpointOccasion {
async fn check_occasion(&self, last_epoch: u64, last_period: u32) -> Result<(), CkbTxErr> {
if (last_period as u64) == self.epoch_len - 1 {
if self.new_checkpoint.period != 0 || self.new_checkpoint.epoch != last_epoch + 1 {
Err(CkbTxErr::NotCheckpointOccasion {
current_epoch: last_epoch,
current_period: last_period,
recorded_epoch: latest_epoch,
recorded_period: last_period,
}),
},
_ => Err(CkbTxErr::NotCheckpointOccasion {
recorded_epoch: self.new_checkpoint.epoch,
recorded_period: self.new_checkpoint.period,
})
} else {
Ok(())
}
} else if self.new_checkpoint.period != last_period + 1
|| self.new_checkpoint.epoch != last_epoch + 1
{
Err(CkbTxErr::NotCheckpointOccasion {
current_epoch: last_epoch,
current_period: last_period,
recorded_epoch: self.new_checkpoint.epoch,
recorded_period: self.new_checkpoint.period,
}),
})
} else {
Ok(())
}
}
}
Loading