diff --git a/Cargo.lock b/Cargo.lock index ba3c3df..5e176ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4424,6 +4424,7 @@ version = "0.1.0" dependencies = [ "anyhow", "arc-swap", + "async-std", "async-trait", "bytes", "ckb-crypto", diff --git a/common/src/traits/ckb_rpc_client.rs b/common/src/traits/ckb_rpc_client.rs index 047b69f..6575746 100644 --- a/common/src/traits/ckb_rpc_client.rs +++ b/common/src/traits/ckb_rpc_client.rs @@ -1,11 +1,12 @@ -use crate::types::{ - BlockNumber, CellWithStatus, JsonBytes, OutPoint, OutputsValidator, Transaction, Uint32, -}; use anyhow::Result; use async_trait::async_trait; use ckb_types::H256; use crate::types::ckb_rpc_client::{Cell, IndexerTip, Order, Pagination, RpcSearchKey, SearchKey}; +use crate::types::{ + BlockNumber, CellWithStatus, JsonBytes, OutPoint, OutputsValidator, Transaction, + TransactionWithStatusResponse, Uint32, +}; #[async_trait] pub trait CkbRpc: Send + Sync + Clone { @@ -28,6 +29,9 @@ pub trait CkbRpc: Send + Sync + Clone { tx: &Transaction, outputs_validator: Option, ) -> Result; + + // Chain + async fn get_transaction(&self, hash: H256) -> Result>; } #[async_trait] diff --git a/common/src/types/mod.rs b/common/src/types/mod.rs index c74d54f..de574e0 100644 --- a/common/src/types/mod.rs +++ b/common/src/types/mod.rs @@ -14,5 +14,6 @@ pub use ethereum_types::{ }; pub use ckb_jsonrpc_types::{ - BlockNumber, CellWithStatus, JsonBytes, OutPoint, OutputsValidator, Transaction, Uint32, + BlockNumber, CellWithStatus, JsonBytes, OutPoint, OutputsValidator, Transaction, + TransactionWithStatusResponse, Uint32, }; diff --git a/common/src/types/tx_builder.rs b/common/src/types/tx_builder.rs index 74ea428..730da82 100644 --- a/common/src/types/tx_builder.rs +++ b/common/src/types/tx_builder.rs @@ -112,7 +112,7 @@ impl From for ADelegateRequirement { } } -#[derive(Clone, Default)] +#[derive(Clone, Default, Debug)] pub struct StakeItem { pub is_increase: bool, pub amount: Amount, @@ -122,7 +122,7 @@ pub struct StakeItem { impl From for StakeInfoDelta { fn from(stake: StakeItem) -> Self { StakeInfoDelta::new_builder() - .is_increase(Byte::new(stake.is_increase.into())) + .is_increase((stake.is_increase as u8).into()) .amount(to_uint128(stake.amount)) .inauguration_epoch(to_uint64(stake.inauguration_epoch)) .build() diff --git a/devtools/tx-tests/README.md b/devtools/tx-tests/README.md index 3c73c2a..a939c64 100644 --- a/devtools/tx-tests/README.md +++ b/devtools/tx-tests/README.md @@ -37,4 +37,6 @@ cargo run -- -s redeem // redeem stake cargo run -- -s first // first delegate cargo run -- -s add // add delegate cargo run -- -s redeem // redeem delegate + +cargo run -- -t // stake smt tx ``` diff --git a/devtools/tx-tests/src/config/type_ids.toml b/devtools/tx-tests/src/config/type_ids.toml index 9029cc1..b81bfac 100644 --- a/devtools/tx-tests/src/config/type_ids.toml +++ b/devtools/tx-tests/src/config/type_ids.toml @@ -1,8 +1,8 @@ -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" +selection_type_id = "0xeab0e0bdde4f92982491e677555dd07da40a95ed4f2a69604c134eb4a930dbb2" +issue_type_id = "0x7b3f21c041745249930a8cb44b31874d81fa07bb6e743fefce0000c4c115c279" +checkpoint_type_id = "0xb4189de7fae992a0cc38deda58dd74562a1d2117eb3cdc75b80359928ffa2618" +metadata_type_id = "0xe9af859142be9effff2f5904d927e697e05573b8f3494109bcd81e6355f51085" +stake_smt_type_id = "0x4f241ed011d51fe81558dbb91450fe92f343d37d180689d0fde8f1047e8a92ff" +delegate_smt_type_id = "0x27cd8265a48095f1b23da490ba3571630c2319dce5f758e8cb4dabc1a9386577" +reward_smt_type_id = "0x8ab9b5a16d1a8c36f9db2472587f065c8fe56da879a82a9eb858908e39fb4529" +xudt_owner = "0x5c9c204f74ceb84e55a66c2570fdf825ce4b1cfe38e76c1c6a0c975f758388c3" diff --git a/devtools/tx-tests/src/main.rs b/devtools/tx-tests/src/main.rs index 1232386..eb40445 100644 --- a/devtools/tx-tests/src/main.rs +++ b/devtools/tx-tests/src/main.rs @@ -49,6 +49,27 @@ async fn main() { .required(false) .num_args(0) .help("test checkpoint tx"), + ) + .arg( + clap::Arg::new("stake smt") + .short('t') + .required(false) + .num_args(0) + .help("test stake smt tx"), + ) + .arg( + clap::Arg::new("delegate smt") + .short('e') + .required(false) + .num_args(0) + .help("test delegate smt tx"), + ) + .arg( + clap::Arg::new("reward") + .short('r') + .required(false) + .num_args(0) + .help("test reward tx"), ); let matches = cmd.get_matches(); @@ -57,6 +78,9 @@ async fn main() { let stake = matches.get_one::("stake").unwrap().as_str(); let delegate = matches.get_one::("delegate").unwrap().as_str(); let checkpoint = matches.get_one::("checkpoint").unwrap().to_owned(); + let stake_smt = matches.get_one::("stake smt").unwrap().to_owned(); + let delegate_smt = matches.get_one::("delegate smt").unwrap().to_owned(); + let reward = matches.get_one::("reward").unwrap().to_owned(); let ckb = CkbRpcClient::new("https://testnet.ckb.dev"); @@ -89,4 +113,16 @@ async fn main() { if checkpoint { checkpoint_tx(&ckb).await; } + + if stake_smt { + stake_smt_tx(&ckb).await; + } + + if delegate_smt { + delegate_smt_tx(&ckb).await; + } + + if reward { + reward_tx(&ckb).await; + } } diff --git a/devtools/tx-tests/src/tx/delegate_smt.rs b/devtools/tx-tests/src/tx/delegate_smt.rs new file mode 100644 index 0000000..57b1ff6 --- /dev/null +++ b/devtools/tx-tests/src/tx/delegate_smt.rs @@ -0,0 +1,67 @@ +use std::{fs, path::PathBuf, vec}; + +use ckb_types::prelude::Pack; +use rpc_client::ckb_client::ckb_rpc_client::CkbRpcClient; +use storage::SmtManager; + +use common::traits::tx_builder::IDelegateSmtTxBuilder; +use common::types::tx_builder::DelegateSmtTypeIds; +use tx_builder::ckb::delegate_smt::DelegateSmtTxBuilder; +use tx_builder::ckb::helper::{Delegate, OmniEth, Tx, Xudt}; + +use crate::config::parse_file; +use crate::config::types::{PrivKeys, TypeIds as CTypeIds}; +use crate::{PRIV_KEYS_PATH, TYPE_IDS_PATH}; + +static ROCKSDB_PATH: &str = "./free-space/smt/delegate"; + +pub async fn delegate_smt_tx(ckb: &CkbRpcClient) { + let priv_keys: PrivKeys = parse_file(PRIV_KEYS_PATH); + let test_kicker_key = priv_keys.delegator_privkeys[0].clone().into_h256().unwrap(); + let omni_eth = OmniEth::new(test_kicker_key.clone()); + println!("kicker ckb addres: {}\n", omni_eth.ckb_address().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 delegate_smt_type_id = type_ids.delegate_smt_type_id.into_h256().unwrap(); + let xudt_owner = type_ids.xudt_owner.into_h256().unwrap(); + + let delegate_cell = Delegate::get_cell( + ckb, + Delegate::lock(&metadata_type_id, &omni_eth.address().unwrap()), + Xudt::type_(&xudt_owner.pack()), + ) + .await + .unwrap() + .unwrap(); + + let path = PathBuf::from(ROCKSDB_PATH); + fs::remove_dir_all(path.clone()).unwrap(); + let smt = SmtManager::new(path); + + let (tx, _) = DelegateSmtTxBuilder::new( + ckb, + test_kicker_key, + 0, + DelegateSmtTypeIds { + metadata_type_id, + checkpoint_type_id, + delegate_smt_type_id, + xudt_owner, + }, + vec![delegate_cell], + smt, + ) + .build_tx() + .await + .unwrap(); + + let mut tx = Tx::new(ckb, tx); + match tx.send().await { + Ok(tx_hash) => println!("tx hash: 0x{}", tx_hash), + Err(e) => println!("{}", e), + } + + println!("\ntx: {}", tx.inner()); +} diff --git a/devtools/tx-tests/src/tx/init.rs b/devtools/tx-tests/src/tx/init.rs index dd14316..0fd635f 100644 --- a/devtools/tx-tests/src/tx/init.rs +++ b/devtools/tx-tests/src/tx/init.rs @@ -1,5 +1,5 @@ use common::traits::tx_builder::IInitTxBuilder; -use common::types::tx_builder::{Checkpoint, Metadata}; +use common::types::tx_builder::{Checkpoint, Metadata, PrivateKey}; use rpc_client::ckb_client::ckb_rpc_client::CkbRpcClient; use tx_builder::ckb::helper::{OmniEth, Tx}; use tx_builder::ckb::init::InitTxBuilder; @@ -16,10 +16,9 @@ pub async fn init_tx(ckb: &CkbRpcClient) { let omni_eth = OmniEth::new(test_seeder_key.clone()); println!("seeder ckb addres: {}\n", omni_eth.ckb_address().unwrap()); - let (tx, type_id_args) = InitTxBuilder::new( + _init_tx( ckb, test_seeder_key, - 10000, Checkpoint { epoch: 0, period: 0, @@ -35,11 +34,21 @@ pub async fn init_tx(ckb: &CkbRpcClient) { ..Default::default() }, ) - .build_tx() - .await - .unwrap(); + .await; +} + +pub async fn _init_tx( + ckb: &CkbRpcClient, + seeder_key: PrivateKey, + checkpoint: Checkpoint, + metadata: Metadata, +) -> Tx { + let (tx, type_id_args) = InitTxBuilder::new(ckb, seeder_key, 10000, checkpoint, metadata) + .build_tx() + .await + .unwrap(); - let tx = Tx::new(ckb, tx); + let mut tx = Tx::new(ckb, tx); match tx.send().await { Ok(tx_hash) => println!("tx hash: 0x{}", tx_hash), @@ -48,4 +57,6 @@ pub async fn init_tx(ckb: &CkbRpcClient) { let type_ids: CTypeIds = type_id_args.into(); write_file(TYPE_IDS_PATH, &type_ids); + + tx } diff --git a/devtools/tx-tests/src/tx/mint.rs b/devtools/tx-tests/src/tx/mint.rs index efd97c6..5a79471 100644 --- a/devtools/tx-tests/src/tx/mint.rs +++ b/devtools/tx-tests/src/tx/mint.rs @@ -14,10 +14,14 @@ pub async fn mint_tx(ckb: &CkbRpcClient) { println!("seeder ckb addres: {}\n", omni_eth.ckb_address().unwrap()); let mut stakers = vec![]; - for staker_privkey in priv_keys.staker_privkeys.into_iter() { + for (i, staker_privkey) in priv_keys.staker_privkeys.into_iter().enumerate() { let privkey = staker_privkey.clone().into_h256().unwrap(); let omni_eth = OmniEth::new(privkey); - println!("staker ckb addres: {}", omni_eth.ckb_address().unwrap()); + println!( + "staker{} ckb addres: {}", + i, + omni_eth.ckb_address().unwrap() + ); stakers.push((omni_eth.address().unwrap(), 200)); } @@ -36,7 +40,7 @@ pub async fn mint_tx(ckb: &CkbRpcClient) { .await .unwrap(); - let tx = Tx::new(ckb, tx); + let mut tx = Tx::new(ckb, tx); match tx.send().await { Ok(tx_hash) => println!("tx hash: 0x{}", tx_hash), diff --git a/devtools/tx-tests/src/tx/mod.rs b/devtools/tx-tests/src/tx/mod.rs index 6f60cde..315c8c3 100644 --- a/devtools/tx-tests/src/tx/mod.rs +++ b/devtools/tx-tests/src/tx/mod.rs @@ -1,11 +1,17 @@ mod checkpoint; mod delegate; +mod delegate_smt; mod init; mod mint; +mod reward; mod stake; +mod stake_smt; pub use checkpoint::checkpoint_tx; pub use delegate::{add_delegate_tx, first_delegate_tx, reedem_delegate_tx}; +pub use delegate_smt::delegate_smt_tx; pub use init::init_tx; pub use mint::mint_tx; +pub use reward::reward_tx; pub use stake::{add_stake_tx, first_stake_tx, reedem_stake_tx}; +pub use stake_smt::stake_smt_tx; diff --git a/devtools/tx-tests/src/tx/reward.rs b/devtools/tx-tests/src/tx/reward.rs new file mode 100644 index 0000000..054e625 --- /dev/null +++ b/devtools/tx-tests/src/tx/reward.rs @@ -0,0 +1,152 @@ +use std::{path::PathBuf, vec}; + +use common::traits::smt::{DelegateSmtStorage, ProposalSmtStorage, StakeSmtStorage}; +use common::traits::tx_builder::IRewardTxBuilder; +use common::types::smt::{Staker, UserAmount}; +use common::types::tx_builder::{Checkpoint, Metadata, RewardInfo, RewardTypeIds}; +use common::utils::convert::to_eth_h160; +use rpc_client::ckb_client::ckb_rpc_client::CkbRpcClient; +use storage::SmtManager; +use tx_builder::ckb::helper::{OmniEth, Tx}; +use tx_builder::ckb::reward::RewardTxBuilder; + +use crate::config::parse_file; +use crate::config::types::{PrivKeys, TypeIds as CTypeIds}; +use crate::tx::init::_init_tx; +use crate::{PRIV_KEYS_PATH, TYPE_IDS_PATH}; + +static ROCKSDB_PATH: &str = "./free-space/smt/reward"; + +pub async fn reward_tx(ckb: &CkbRpcClient) { + let priv_keys: PrivKeys = parse_file(PRIV_KEYS_PATH); + + let test_seeder_key = priv_keys.seeder_privkey.into_h256().unwrap(); + println!( + "seeder ckb addres: {}\n", + OmniEth::new(test_seeder_key.clone()).ckb_address().unwrap() + ); + + let tx = _init_tx( + ckb, + test_seeder_key, + Checkpoint { + epoch: 0, + period: 0, + latest_block_height: 10, + timestamp: 11111, + ..Default::default() + }, + Metadata { + epoch_len: 100, + period_len: 100, + quorum: 10, + validators: vec![], + ..Default::default() + }, + ) + .await; + + tx.wait_until_committed(1000, 10).await.unwrap(); + println!("init tx committed"); + + let test_staker_key = priv_keys.staker_privkeys[0].clone().into_h256().unwrap(); + let omni_eth = OmniEth::new(test_staker_key.clone()); + println!("staker ckb addres: {}\n", omni_eth.ckb_address().unwrap()); + let staker = omni_eth.address().unwrap(); + + let type_ids: CTypeIds = parse_file(TYPE_IDS_PATH); + + let path = PathBuf::from(ROCKSDB_PATH); + let smt = SmtManager::new(path); + mock_smt(&smt, to_eth_h160(&staker)).await; + + let tx = RewardTxBuilder::new( + ckb, + RewardTypeIds { + selection_type_id: type_ids.selection_type_id.into_h256().unwrap(), + metadata_type_id: type_ids.metadata_type_id.into_h256().unwrap(), + checkpoint_type_id: type_ids.checkpoint_type_id.into_h256().unwrap(), + reward_smt_type_id: type_ids.reward_smt_type_id.into_h256().unwrap(), + stake_smt_type_id: type_ids.stake_smt_type_id.into_h256().unwrap(), + delegate_smt_type_id: type_ids.delegate_smt_type_id.into_h256().unwrap(), + xudt_owner: type_ids.xudt_owner.into_h256().unwrap(), + }, + smt, + RewardInfo { + base_reward: 100, + half_reward_cycle: 200, + theoretical_propose_count: 30, + epoch_count: 10, + }, + staker, + 5, + ) + .build_tx() + .await + .unwrap(); + + let mut tx = Tx::new(ckb, tx); + + let script_groups = tx.gen_script_group().await.unwrap(); + let signer = omni_eth.signer().unwrap(); + + for (i, group) in script_groups.lock_groups.iter().enumerate() { + if i <= 1 { + println!("not sign: {:?}", group.1.input_indices); + } else { + println!("sign: {:?}", group.1.input_indices); + tx.sign(&signer, group.1).unwrap(); + } + } + + match tx.send().await { + Ok(tx_hash) => println!("tx hash: 0x{}", tx_hash), + Err(e) => println!("{}", e), + } +} + +async fn mock_smt(smt: &SmtManager, staker: Staker) { + mock_stake_smt(smt, staker).await; + mock_delegate_smt(smt, staker).await; + mock_proposal_smt(smt, staker).await; +} + +async fn mock_stake_smt(smt: &SmtManager, staker: Staker) { + let epoch = 2; + let amount = 100u128; + + let amounts = vec![UserAmount { + user: staker, + amount, + is_increase: true, + }]; + + StakeSmtStorage::insert(smt, epoch, amounts).await.unwrap(); +} + +async fn mock_delegate_smt(smt: &SmtManager, staker: Staker) { + let delegator = [6u8; 20].into(); + let epoch = 2; + let amount = 100u128; + + let delegators = vec![UserAmount { + user: delegator, + amount, + is_increase: true, + }]; + + DelegateSmtStorage::insert(smt, epoch, staker, delegators.clone()) + .await + .unwrap(); +} + +async fn mock_proposal_smt(smt: &SmtManager, validator: Staker) { + let epoch = 0; + let proposal_count = 10; + + let proposals = vec![(validator, proposal_count)]; + + ProposalSmtStorage::insert(smt, epoch, proposals) + .await + .unwrap(); +} diff --git a/devtools/tx-tests/src/tx/stake.rs b/devtools/tx-tests/src/tx/stake.rs index 2cf2dca..8b1f459 100644 --- a/devtools/tx-tests/src/tx/stake.rs +++ b/devtools/tx-tests/src/tx/stake.rs @@ -22,7 +22,7 @@ pub async fn first_stake_tx(ckb: &CkbRpcClient) { ckb, StakeItem { is_increase: true, - amount: 10, + amount: 100, inauguration_epoch: 2, }, 0, @@ -80,7 +80,7 @@ async fn stake_tx( let priv_keys: PrivKeys = parse_file(PRIV_KEYS_PATH); let test_staker_key = priv_keys.staker_privkeys[0].clone().into_h256().unwrap(); let omni_eth = OmniEth::new(test_staker_key.clone()); - println!("staker ckb addres: {}\n", omni_eth.ckb_address().unwrap()); + println!("staker0 ckb addres: {}\n", omni_eth.ckb_address().unwrap()); let first_stake = first_stake_info.is_some(); let type_ids: CTypeIds = parse_file(TYPE_IDS_PATH); diff --git a/devtools/tx-tests/src/tx/stake_smt.rs b/devtools/tx-tests/src/tx/stake_smt.rs new file mode 100644 index 0000000..b0fcd69 --- /dev/null +++ b/devtools/tx-tests/src/tx/stake_smt.rs @@ -0,0 +1,68 @@ +use std::{fs, path::PathBuf, vec}; + +use ckb_types::prelude::Pack; +use rpc_client::ckb_client::ckb_rpc_client::CkbRpcClient; +use storage::SmtManager; + +use common::traits::tx_builder::IStakeSmtTxBuilder; +use common::types::tx_builder::StakeSmtTypeIds; +use tx_builder::ckb::helper::{OmniEth, Stake, Tx, Xudt}; +use tx_builder::ckb::stake_smt::StakeSmtTxBuilder; + +use crate::config::parse_file; +use crate::config::types::{PrivKeys, TypeIds as CTypeIds}; +use crate::{PRIV_KEYS_PATH, TYPE_IDS_PATH}; + +static ROCKSDB_PATH: &str = "./free-space/smt/stake"; + +pub async fn stake_smt_tx(ckb: &CkbRpcClient) { + let priv_keys: PrivKeys = parse_file(PRIV_KEYS_PATH); + let test_kicker_key = priv_keys.staker_privkeys[0].clone().into_h256().unwrap(); + let omni_eth = OmniEth::new(test_kicker_key.clone()); + println!("kicker ckb addres: {}\n", omni_eth.ckb_address().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 stake_smt_type_id = type_ids.stake_smt_type_id.into_h256().unwrap(); + let xudt_owner = type_ids.xudt_owner.into_h256().unwrap(); + + let stake_cell = Stake::get_cell( + ckb, + Stake::lock(&metadata_type_id, &omni_eth.address().unwrap()), + Xudt::type_(&xudt_owner.pack()), + ) + .await + .unwrap() + .unwrap(); + + let path = PathBuf::from(ROCKSDB_PATH); + fs::remove_dir_all(path.clone()).unwrap(); + let smt = SmtManager::new(path); + + let (tx, _) = StakeSmtTxBuilder::new( + ckb, + test_kicker_key, + 0, + StakeSmtTypeIds { + metadata_type_id, + checkpoint_type_id, + stake_smt_type_id, + xudt_owner, + }, + 10, + vec![stake_cell], + smt, + ) + .build_tx() + .await + .unwrap(); + + let mut tx = Tx::new(ckb, tx); + match tx.send().await { + Ok(tx_hash) => println!("tx hash: 0x{}", tx_hash), + Err(e) => println!("{}", e), + } + + println!("\ntx: {}", tx.inner()); +} diff --git a/rpc-client/src/ckb_client/ckb_rpc_client.rs b/rpc-client/src/ckb_client/ckb_rpc_client.rs index be75ebf..7e7a2be 100644 --- a/rpc-client/src/ckb_client/ckb_rpc_client.rs +++ b/rpc-client/src/ckb_client/ckb_rpc_client.rs @@ -1,7 +1,8 @@ use anyhow::Result; use async_trait::async_trait; use ckb_jsonrpc_types::{ - CellWithStatus, JsonBytes, OutPoint, OutputsValidator, Transaction, Uint32, + CellWithStatus, JsonBytes, OutPoint, OutputsValidator, Transaction, + TransactionWithStatusResponse, Uint32, }; use ckb_types::H256; use common::{ @@ -120,6 +121,18 @@ impl CkbRpcClient { ) -> impl Future> { jsonrpc!("send_transaction", self, H256, tx, outputs_validator) } + + pub fn get_transaction( + &self, + hash: H256, + ) -> impl Future>> { + jsonrpc!( + "get_transaction", + self, + Option, + hash + ) + } } #[async_trait] @@ -149,4 +162,8 @@ impl CkbRpc for CkbRpcClient { ) -> Result { self.send_transaction(tx, outputs_validator).await } + + async fn get_transaction(&self, hash: H256) -> Result> { + self.get_transaction(hash).await + } } diff --git a/tx-builder/Cargo.toml b/tx-builder/Cargo.toml index d5b1ed7..c8cf2bf 100644 --- a/tx-builder/Cargo.toml +++ b/tx-builder/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] anyhow = "1.0" arc-swap = "1.6" +async-std = "1.12" async-trait = "0.1" bytes = "1.0" ckb-crypto = "0.108" diff --git a/tx-builder/src/ckb/checkpoint.rs b/tx-builder/src/ckb/checkpoint.rs index 9873d76..9d6abc5 100644 --- a/tx-builder/src/ckb/checkpoint.rs +++ b/tx-builder/src/ckb/checkpoint.rs @@ -1,6 +1,6 @@ use anyhow::Result; use async_trait::async_trait; -use ckb_sdk::{unlock::ScriptSigner, ScriptGroup, ScriptGroupType}; +use ckb_sdk::{ScriptGroup, ScriptGroupType}; use ckb_types::{ core::{Capacity, TransactionBuilder, TransactionView}, packed::{CellInput, CellOutput, WitnessArgs}, @@ -129,17 +129,17 @@ where let omni_eth = OmniEth::new(self.kicker_key.clone()); let kick_lock = OmniEth::lock(&omni_eth.address()?); - let tx = Tx::new(self.ckb, tx).balance(kick_lock.clone()).await?; + let mut tx = Tx::new(self.ckb, tx); + tx.balance(kick_lock.clone()).await?; - let signer = omni_eth.signer()?; - let tx_view = signer.sign_tx(&tx, &ScriptGroup { + tx.sign(&omni_eth.signer()?, &ScriptGroup { script: kick_lock, group_type: ScriptGroupType::Lock, input_indices: vec![1], output_indices: vec![], })?; - Ok(tx_view) + Ok(tx.inner()) } } diff --git a/tx-builder/src/ckb/define/scripts.rs b/tx-builder/src/ckb/define/scripts.rs index 4ac6090..2a2b086 100644 --- a/tx-builder/src/ckb/define/scripts.rs +++ b/tx-builder/src/ckb/define/scripts.rs @@ -150,7 +150,7 @@ lazy_static::lazy_static! { pub static ref STAKE_LOCK_TESTNET: Script = Script { code_hash: h256!("0x0a2adef4af62c9350eee7d31dfc2b5f340f2fa5c5d70f6834c13465cb545cde3"), hash_type: ScriptHashType::Type, - tx_hash: h256!("0x036abf118006a72129d57f8daa841e7dbab56aeb2f8c356f74618665a9bb4429"), + tx_hash: h256!("0x790bf6c94a9ef39ea353c98deb77a238b113580676fa2de86bc547f0d3a55a5d"), index: 0, dep_type: DepType::Code, }; @@ -166,7 +166,7 @@ lazy_static::lazy_static! { pub static ref STAKE_SMT_TYPE_TESTNET: Script = Script { code_hash: h256!("0x4b40fbfc384278eb1a8bcda34a08b37642d33d49a804e56185926ff6e779e01d"), hash_type: ScriptHashType::Type, - tx_hash: h256!("0x036abf118006a72129d57f8daa841e7dbab56aeb2f8c356f74618665a9bb4429"), + tx_hash: h256!("0x790bf6c94a9ef39ea353c98deb77a238b113580676fa2de86bc547f0d3a55a5d"), index: 1, dep_type: DepType::Code, }; @@ -219,7 +219,7 @@ lazy_static::lazy_static! { dep_type: DepType::Code, }; - // todo + // todo: main net pub static ref WITHDRAW_LOCK_MAINNET: Script = Script { code_hash: h256!("0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"), hash_type: ScriptHashType::Type, @@ -228,14 +228,14 @@ lazy_static::lazy_static! { dep_type: DepType::Code, }; pub static ref WITHDRAW_LOCK_TESTNET: Script = Script { - code_hash: h256!("0x58c63de75a92d3ed83a0636d29454173608ff27a053891258e96a9a44e84ce37"), + code_hash: h256!("0xf33d2e1805347e62ff162bb8d2abf62cd386cdc9af6c455aafa4aa6ecaefbc0d"), hash_type: ScriptHashType::Type, - tx_hash: h256!("0xc2721314c82baf732583e3e0612b7735d0e0af87994b89b3ce6c33f51c1095fb"), + tx_hash: h256!("0x9221b656d96c231d619c8fe34cbc1845702fe1c1998ec8f5c395fd5abd612373"), index: 0, dep_type: DepType::Code, }; - // todo + // todo: main net pub static ref REWARD_SMT_TYPE_MAINNET: Script = Script { code_hash: h256!("0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"), hash_type: ScriptHashType::Type, @@ -244,9 +244,9 @@ lazy_static::lazy_static! { dep_type: DepType::Code, }; pub static ref REWARD_SMT_TYPE_TESTNET: Script = Script { - code_hash: h256!("0x58c63de75a92d3ed83a0636d29454173608ff27a053891258e96a9a44e84ce37"), + code_hash: h256!("0x22b1350ab5764d255bed11c51283a8a462bcfbdf42c42eb13f4bcb8da6cbe867"), hash_type: ScriptHashType::Type, - tx_hash: h256!("0xc2721314c82baf732583e3e0612b7735d0e0af87994b89b3ce6c33f51c1095fb"), + tx_hash: h256!("0xb937a8938d588cddf38bab8273ce474f5d29dce6d0f9ac8c2d49b9bbe25e84b7"), index: 0, dep_type: DepType::Code, }; diff --git a/tx-builder/src/ckb/define/types.rs b/tx-builder/src/ckb/define/types.rs index f22fc17..d9ca279 100644 --- a/tx-builder/src/ckb/define/types.rs +++ b/tx-builder/src/ckb/define/types.rs @@ -1,12 +1,14 @@ -use ckb_types::{H160, H256}; +use ckb_types::{packed::Byte32 as CByte32, H160, H256}; use molecule::prelude::{Builder, Entity}; use common::types::axon_types::{ basic::{Byte32, Byte48, Byte65, Identity}, delegate::{ DelegateAtCellData as ADelegateAtCellData, - DelegateAtCellLockData as ADelegateAtCellLockData, DelegateInfoDeltas, - DelegateSmtCellData as ADelegateSmtCellData, StakerSmtRoot as AStakerSmtRoot, + DelegateAtCellLockData as ADelegateAtCellLockData, DelegateInfo as ADelegateInfo, + DelegateInfoDeltas, DelegateInfos, DelegateSmtCellData as ADelegateSmtCellData, + DelegateSmtUpdateInfo as ADelegateSmtUpdateInfo, DelegateSmtWitness as ADelegateSmtWitness, + StakeGroupInfo as AStakeGroupInfo, StakeGroupInfos, StakerSmtRoot as AStakerSmtRoot, StakerSmtRoots, }, metadata::{MetadataCellData as AMetadataCellData, MetadataList}, @@ -20,7 +22,7 @@ use common::types::axon_types::{ stake::{ StakeAtCellData as AStakeAtCellData, StakeAtCellLockData as AStakeAtCellLockData, StakeInfo as AStakeInfo, StakeInfos, StakeSmtCellData as AStakeSmtCellData, - StakeSmtUpdateInfo as AStakeSmtUpdateInfo, + StakeSmtUpdateInfo as AStakeSmtUpdateInfo, StakeSmtWitness as AStakeSmtWitness, }, withdraw::{ WithdrawAtCellData as AWithdrawAtCellData, @@ -32,6 +34,38 @@ use common::types::smt::{Proof, Root as SmtRoot}; use common::types::tx_builder::*; use common::utils::convert::*; +pub struct DelegateSmtWitness { + pub mode: u8, + pub update_info: DelegateSmtUpdateInfo, +} + +impl From for ADelegateSmtWitness { + fn from(v: DelegateSmtWitness) -> Self { + ADelegateSmtWitness::new_builder() + .mode(v.mode.into()) + .update_info(v.update_info.into()) + .build() + } +} + +pub struct DelegateSmtUpdateInfo { + pub all_stake_group_infos: Vec, +} + +impl From for ADelegateSmtUpdateInfo { + fn from(v: DelegateSmtUpdateInfo) -> Self { + ADelegateSmtUpdateInfo::new_builder() + .all_stake_group_infos({ + let mut list = StakeGroupInfos::new_builder(); + for i in v.all_stake_group_infos.into_iter() { + list = list.push(i.into()); + } + list.build() + }) + .build() + } +} + #[derive(Clone, Default)] pub struct StakeGroupInfo { pub staker: H160, @@ -40,12 +74,38 @@ pub struct StakeGroupInfo { pub delegate_new_epoch_proof: Vec, } +impl From for AStakeGroupInfo { + fn from(v: StakeGroupInfo) -> Self { + AStakeGroupInfo::new_builder() + .staker(to_identity(&v.staker)) + .delegate_old_epoch_proof(to_bytes(v.delegate_old_epoch_proof)) + .delegate_new_epoch_proof(to_bytes(v.delegate_new_epoch_proof)) + .delegate_infos({ + let mut list = DelegateInfos::new_builder(); + for d in v.delegate_infos.into_iter() { + list = list.push(d.into()); + } + list.build() + }) + .build() + } +} + #[derive(Clone, Default)] pub struct DelegateInfo { pub delegator_addr: H160, pub amount: u128, } +impl From for ADelegateInfo { + fn from(v: DelegateInfo) -> Self { + ADelegateInfo::new_builder() + .delegator_addr(to_identity(&v.delegator_addr)) + .amount(to_uint128(v.amount)) + .build() + } +} + #[derive(Clone, Default)] pub struct StakerSmtRoot { pub staker: H160, @@ -64,15 +124,15 @@ impl From for AStakerSmtRoot { #[derive(Clone, Default)] pub struct DelegateSmtCellData { // pub version: u8, // useless - pub metadata_type_id: H256, - pub smt_roots: Vec, // smt root of all delegator infos + pub metadata_type_hash: CByte32, + pub smt_roots: Vec, // smt root of all delegator infos } impl From for ADelegateSmtCellData { fn from(value: DelegateSmtCellData) -> Self { ADelegateSmtCellData::new_builder() // .version(value.version.into()) // useless - .metadata_type_id(to_byte32(&value.metadata_type_id)) + .metadata_type_id(to_axon_byte32(&value.metadata_type_hash)) .smt_roots({ let mut list = StakerSmtRoots::new_builder(); for r in value.smt_roots.into_iter() { @@ -84,17 +144,16 @@ impl From for ADelegateSmtCellData { } } -#[derive(Clone, Default)] -pub struct StakeInfo { - pub addr: H160, - pub amount: u128, +pub struct StakeSmtWitness { + pub mode: u8, // 0 is update stake at cell itself, 1 is update stake smt cell + pub update_info: StakeSmtUpdateInfo, } -impl From for AStakeInfo { - fn from(value: StakeInfo) -> Self { - AStakeInfo::new_builder() - .addr(to_identity(&value.addr)) - .amount(to_uint128(value.amount)) +impl From for AStakeSmtWitness { + fn from(v: StakeSmtWitness) -> Self { + AStakeSmtWitness::new_builder() + .mode(v.mode.into()) + .update_info(v.update_info.into()) .build() } } @@ -102,8 +161,8 @@ impl From for AStakeInfo { #[derive(Clone, Default)] pub struct StakeSmtUpdateInfo { pub all_stake_infos: Vec, - pub old_epoch_proof: Vec, - pub new_epoch_proof: Vec, + pub old_epoch_proof: Proof, + pub new_epoch_proof: Proof, } impl From for AStakeSmtUpdateInfo { @@ -122,18 +181,33 @@ impl From for AStakeSmtUpdateInfo { } } +#[derive(Clone, Default)] +pub struct StakeInfo { + pub addr: H160, + pub amount: u128, +} + +impl From for AStakeInfo { + fn from(value: StakeInfo) -> Self { + AStakeInfo::new_builder() + .addr(to_identity(&value.addr)) + .amount(to_uint128(value.amount)) + .build() + } +} + #[derive(Clone, Default)] pub struct StakeSmtCellData { // pub version: u8, // useless - pub metadata_type_id: H256, - pub smt_root: SmtRoot, + pub metadata_type_hash: CByte32, + pub smt_root: SmtRoot, } impl From for AStakeSmtCellData { fn from(v: StakeSmtCellData) -> Self { AStakeSmtCellData::new_builder() .smt_root(Byte32::from_slice(v.smt_root.as_slice()).unwrap()) - .metadata_type_id(to_byte32(&v.metadata_type_id)) + .metadata_type_id(to_axon_byte32(&v.metadata_type_hash)) .build() } } @@ -284,15 +358,15 @@ impl From for AMetadataCellData { #[derive(Default)] pub struct RewardSmtCellData { - pub claim_smt_root: SmtRoot, - pub metadata_type_id: H256, + pub claim_smt_root: SmtRoot, + pub metadata_type_hash: CByte32, } impl From for ARewardSmtCellData { fn from(v: RewardSmtCellData) -> Self { ARewardSmtCellData::new_builder() .claim_smt_root(Byte32::from_slice(v.claim_smt_root.as_slice()).unwrap()) - .metadata_type_id(to_byte32(&v.metadata_type_id)) + .metadata_type_id(to_axon_byte32(&v.metadata_type_hash)) .build() } } diff --git a/tx-builder/src/ckb/delegate.rs b/tx-builder/src/ckb/delegate.rs index f160266..ff59ec5 100644 --- a/tx-builder/src/ckb/delegate.rs +++ b/tx-builder/src/ckb/delegate.rs @@ -127,11 +127,10 @@ impl<'a, C: CkbRpc> DelegateTxBuilder<'a, C> { .witnesses(witnesses.pack()) .build(); - let tx = Tx::new(self.ckb, tx) - .balance(self.token_lock.clone()) - .await?; + let mut tx = Tx::new(self.ckb, tx); + tx.balance(self.token_lock.clone()).await?; - Ok(tx) + Ok(tx.inner()) } async fn build_update_delegate_tx(&self, delegate_cell: Cell) -> Result { @@ -168,9 +167,9 @@ impl<'a, C: CkbRpc> DelegateTxBuilder<'a, C> { ]; let witnesses = vec![ - Delegate::witness_placeholder(0u8).as_bytes(), // delegate AT cell lock, todo - OmniEth::witness_placeholder().as_bytes(), // AT cell lock - OmniEth::witness_placeholder().as_bytes(), // capacity provider lock + Delegate::witness(0u8).as_bytes(), // delegate AT cell lock, todo + OmniEth::witness_placeholder().as_bytes(), // AT cell lock + OmniEth::witness_placeholder().as_bytes(), // capacity provider lock ]; let tx = TransactionBuilder::default() @@ -181,11 +180,10 @@ impl<'a, C: CkbRpc> DelegateTxBuilder<'a, C> { .witnesses(witnesses.pack()) .build(); - let tx = Tx::new(self.ckb, tx) - .balance(self.token_lock.clone()) - .await?; + let mut tx = Tx::new(self.ckb, tx); + tx.balance(self.token_lock.clone()).await?; - Ok(tx) + Ok(tx.inner()) } async fn add_token_to_intpus(&self, inputs: &mut Vec) -> Result { diff --git a/tx-builder/src/ckb/delegate_smt.rs b/tx-builder/src/ckb/delegate_smt.rs index 4a2d313..a119315 100644 --- a/tx-builder/src/ckb/delegate_smt.rs +++ b/tx-builder/src/ckb/delegate_smt.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use anyhow::Result; use async_trait::async_trait; +use ckb_sdk::{ScriptGroup, ScriptGroupType}; use ckb_types::{ bytes::Bytes, core::{Capacity, TransactionBuilder, TransactionView}, @@ -15,8 +16,7 @@ use common::traits::{ }; use common::types::axon_types::delegate::{ DelegateArgs, DelegateAtCellData, DelegateAtCellLockData as ADelegateAtCellLockData, - DelegateAtWitness, DelegateCellData, DelegateInfoDeltas, - DelegateSmtCellData as ADelegateSmtCellData, + DelegateCellData, DelegateInfoDeltas, DelegateSmtCellData as ADelegateSmtCellData, }; use common::types::ckb_rpc_client::Cell; use common::types::smt::{Delegator as SmtDelegator, UserAmount}; @@ -105,6 +105,8 @@ impl<'a, C: CkbRpc, D: DelegateSmtStorage> IDelegateSmtTxBuilder<'a, C, D> ) .await?; + witnesses.push(OmniEth::witness_placeholder().as_bytes()); // capacity provider lock + let cell_deps = vec![ Secp256k1::lock_dep(), OmniEth::lock_dep(), @@ -127,11 +129,18 @@ impl<'a, C: CkbRpc, D: DelegateSmtStorage> IDelegateSmtTxBuilder<'a, C, D> let omni_eth = OmniEth::new(self.kicker.clone()); let kicker_lock = OmniEth::lock(&omni_eth.address()?); - let tx = Tx::new(self.ckb, tx).balance(kicker_lock).await?; - // todo: sign tx + let mut tx = Tx::new(self.ckb, tx); + tx.balance(kicker_lock.clone()).await?; + + tx.sign(&omni_eth.signer()?, &ScriptGroup { + script: kicker_lock, + group_type: ScriptGroupType::Lock, + input_indices: vec![tx.inner_ref().inputs().len() - 1], + output_indices: vec![], + })?; - Ok((tx, statistics.non_top_delegators)) + Ok((tx.inner(), statistics.non_top_delegators)) } } @@ -158,7 +167,7 @@ impl<'a, C: CkbRpc, D: DelegateSmtStorage> DelegateSmtTxBuilder<'a, C, D> { .previous_output(delegate_cell.out_point.clone().into()) .build(), ); - witnesses.push(self.delegate_at_witness().as_bytes()); + witnesses.push(Delegate::witness(1).as_bytes()); let (old_total_delegate_amount, old_delegate_data) = self.parse_delegate_data(delegate_cell); @@ -178,7 +187,7 @@ impl<'a, C: CkbRpc, D: DelegateSmtStorage> DelegateSmtTxBuilder<'a, C, D> { .previous_output(old_withdraw_cell.out_point.clone().into()) .build(), ); - witnesses.push(self.delegate_at_witness().as_bytes()); + witnesses.push(Withdraw::witness(true).as_bytes()); let withdraw_amounts = statistics.withdraw_amounts.get(delegator).unwrap(); let mut delegator_infos: Vec = Vec::new(); @@ -282,13 +291,6 @@ impl<'a, C: CkbRpc, D: DelegateSmtStorage> DelegateSmtTxBuilder<'a, C, D> { Ok(()) } - fn delegate_at_witness(&self) -> WitnessArgs { - let stake_at_witness = DelegateAtWitness::new_builder().mode(1.into()).build(); - WitnessArgs::new_builder() - .lock(Some(stake_at_witness.as_bytes()).pack()) - .build() - } - fn parse_delegate_data(&self, cell: &Cell) -> (Amount, DelegateAtCellData) { let mut cell_data_bytes = cell.output_data.clone().unwrap().into_bytes(); let total_delegate_amount = new_u128(&cell_data_bytes[..TOKEN_BYTES]); @@ -312,16 +314,6 @@ impl<'a, C: CkbRpc, D: DelegateSmtStorage> DelegateSmtTxBuilder<'a, C, D> { .get_sub_leaves(self.current_epoch + INAUGURATION, to_eth_h160(staker)) .await?; - // get the old epoch proof for witness - let old_epoch_proof = self - .delegate_smt_storage - .generate_sub_proof( - to_eth_h160(staker), - self.current_epoch + INAUGURATION, - old_smt.clone().into_keys().collect(), - ) - .await?; - let mut new_smt = old_smt.clone(); for (delegator, delegate) in delegators.iter() { @@ -362,21 +354,28 @@ impl<'a, C: CkbRpc, D: DelegateSmtStorage> DelegateSmtTxBuilder<'a, C, D> { ) .await?; + // get the old epoch proof for witness + let old_epoch_proof = self + .delegate_smt_storage + .generate_top_proof(vec![self.current_epoch + INAUGURATION], to_eth_h160(staker)) + .await?; + + new_roots.push( + self.update_delegate_smt(staker.clone(), new_smt.clone()) + .await?, + ); + // get the new epoch proof for witness let new_epoch_proof = self .delegate_smt_storage - .generate_sub_proof( - to_eth_h160(staker), - self.current_epoch + INAUGURATION, - new_smt.clone().into_keys().collect(), - ) + .generate_top_proof(vec![self.current_epoch + INAUGURATION], to_eth_h160(staker)) .await?; delegate_infos.push(StakeGroupInfo { staker: staker.clone(), delegate_old_epoch_proof: old_epoch_proof, delegate_new_epoch_proof: new_epoch_proof, - delegate_infos: new_smt + delegate_infos: old_smt .clone() .into_iter() .map(|(addr, amount)| DelegateInfo { @@ -385,21 +384,20 @@ impl<'a, C: CkbRpc, D: DelegateSmtStorage> DelegateSmtTxBuilder<'a, C, D> { }) .collect(), }); - - new_roots.push(self.update_delegate_smt(staker.clone(), new_smt).await?); } Ok(( ADelegateSmtCellData::from(DelegateSmtCellData { - metadata_type_id: self.type_ids.metadata_type_id.clone(), - smt_roots: new_roots, + metadata_type_hash: Metadata::type_(&self.type_ids.metadata_type_id) + .calc_script_hash(), + smt_roots: new_roots, }) .as_bytes(), Statistics { non_top_delegators, withdraw_amounts, }, - Delegate::smt_witness(delegate_infos), + Delegate::smt_witness(0, delegate_infos), )) } diff --git a/tx-builder/src/ckb/helper/ckb/tx.rs b/tx-builder/src/ckb/helper/ckb/tx.rs index c0a3f32..4c8319c 100644 --- a/tx-builder/src/ckb/helper/ckb/tx.rs +++ b/tx-builder/src/ckb/helper/ckb/tx.rs @@ -1,16 +1,18 @@ use anyhow::Result; -use ckb_jsonrpc_types::OutputsValidator; +use ckb_jsonrpc_types::{OutputsValidator, Status}; use ckb_sdk::types::ScriptGroup; use ckb_sdk::unlock::ScriptSigner; use ckb_types::{ core::{Capacity, TransactionView}, packed::{Byte32, Bytes, CellInput, CellOutput, Script}, prelude::*, + H256, }; use linked_hash_map::LinkedHashMap; use common::traits::ckb_rpc_client::CkbRpc; use common::types::ckb_rpc_client::{ScriptType, SearchKey}; +use common::types::TransactionWithStatusResponse; use crate::ckb::define::constants::FEE_RATE; use crate::ckb::define::error::CkbTxErr; @@ -19,8 +21,9 @@ use crate::ckb::helper::ckb::cell_collector::{get_live_cell, get_live_cells}; const KB: u64 = 1000; pub struct Tx<'a, C: CkbRpc> { - tx: TransactionView, - rpc: &'a C, + rpc: &'a C, + tx: TransactionView, + tx_hash: H256, } pub struct ScriptGroups { @@ -30,17 +33,33 @@ pub struct ScriptGroups { impl<'a, C: CkbRpc> Tx<'a, C> { pub fn new(rpc: &'a C, tx: TransactionView) -> Self { - Self { tx, rpc } + Self { + rpc, + tx, + tx_hash: H256::default(), + } } pub fn inner(self) -> TransactionView { self.tx } + pub fn inner_clone(&self) -> TransactionView { + self.tx.clone() + } + + pub fn inner_ref(&self) -> &TransactionView { + &self.tx + } + + pub fn set_tx(&mut self, tx: TransactionView) { + self.tx = tx; + } + /// There is no pure CKB cell in the input and output of the transaction. /// Collect CKB cells and add them to the input of the transaction. /// Add a CKB change cell to the output of the transaction. - pub async fn balance(mut self, capacity_provider: Script) -> Result { + pub async fn balance(&mut self, capacity_provider: Script) -> Result<()> { let outputs_capacity = self.add_ckb_to_outputs(capacity_provider.clone())?; let inputs_capacity = self @@ -49,7 +68,7 @@ impl<'a, C: CkbRpc> Tx<'a, C> { self.change_ckb(inputs_capacity, outputs_capacity)?; - Ok(self.tx) + Ok(()) } pub fn sign(&mut self, signer: &impl ScriptSigner, script_group: &ScriptGroup) -> Result<()> { @@ -57,13 +76,37 @@ impl<'a, C: CkbRpc> Tx<'a, C> { Ok(()) } - pub async fn send(&self) -> Result { + pub async fn send(&mut self) -> Result { let outputs_validator = Some(OutputsValidator::Passthrough); - let tx_hash = self + self.tx_hash = self .rpc .send_transaction(&(self.tx.data().into()), outputs_validator) .await?; - Ok(tx_hash.to_string()) + Ok(self.tx_hash.to_string()) + } + + pub async fn query_status(&self) -> Result> { + self.rpc.get_transaction(self.tx_hash.clone()).await + } + + pub async fn wait_until_committed(&self, interval_ms: u64, max_try: u64) -> Result<()> { + let mut status = Status::Proposed; + let mut try_count = 0; + + while status != Status::Committed { + if let Some(tx_with_status) = self.rpc.get_transaction(self.tx_hash.clone()).await? { + status = tx_with_status.tx_status.status; + } + + try_count += 1; + if try_count >= max_try { + break; + } + + async_std::task::sleep(tokio::time::Duration::from_millis(interval_ms)).await; + } + + Ok(()) } pub async fn gen_script_group(&self) -> Result { diff --git a/tx-builder/src/ckb/helper/delegate.rs b/tx-builder/src/ckb/helper/delegate.rs index 2d5e75f..41bdc7b 100644 --- a/tx-builder/src/ckb/helper/delegate.rs +++ b/tx-builder/src/ckb/helper/delegate.rs @@ -6,15 +6,15 @@ use ckb_types::{H160, H256}; use common::traits::ckb_rpc_client::CkbRpc; use common::types::axon_types::delegate::{ - DelegateArgs, DelegateAtWitness, DelegateInfo, DelegateInfoDelta, DelegateInfos, - DelegateRequirementArgs, DelegateSmtUpdateInfo, DelegateSmtWitness, StakeGroupInfoBuilder, - StakeGroupInfos, + DelegateArgs, DelegateAtWitness, DelegateInfoDelta, DelegateRequirementArgs, + DelegateSmtWitness as ADelegateSmtWitness, }; use common::types::ckb_rpc_client::Cell; use common::types::tx_builder::{DelegateItem, NetworkType}; use common::utils::convert::*; -use crate::ckb::define::{scripts::*, types::StakeGroupInfo}; +use crate::ckb::define::scripts::*; +use crate::ckb::define::types::{DelegateSmtUpdateInfo, DelegateSmtWitness, StakeGroupInfo}; use crate::ckb::helper::ckb::cell_collector::{get_cell_by_scripts, get_cell_by_type}; use crate::ckb::helper::metadata::Metadata; use crate::ckb::helper::unique_cell_dep; @@ -136,14 +136,6 @@ impl Delegate { } } - // todo: eth sig placeholder - pub fn witness_placeholder(mode: u8) -> WitnessArgs { - let lock_field = DelegateAtWitness::new_builder().mode(mode.into()).build(); - WitnessArgs::new_builder() - .lock(Some(lock_field.as_bytes()).pack()) - .build() - } - pub fn item(delegate: &DelegateInfoDelta) -> DelegateItem { DelegateItem { staker: to_h160(&delegate.staker()), @@ -156,10 +148,10 @@ impl Delegate { pub async fn get_cell( ckb_rpc: &impl CkbRpc, - stake_lock: Script, + delegate_lock: Script, xudt: Script, ) -> Result> { - get_cell_by_scripts(ckb_rpc, stake_lock, xudt).await + get_cell_by_scripts(ckb_rpc, delegate_lock, xudt).await } pub async fn get_requirement_cell( @@ -173,37 +165,28 @@ impl Delegate { get_cell_by_type(ckb_rpc, delegate_smt_type).await } - pub fn smt_witness(all_delegate_infos: Vec) -> WitnessArgs { - let delegate_update_infos = DelegateSmtUpdateInfo::new_builder() - .all_stake_group_infos( - StakeGroupInfos::new_builder() - .extend(all_delegate_infos.into_iter().map(|i| { - StakeGroupInfoBuilder::default() - .staker(to_identity(&i.staker)) - .delegate_new_epoch_proof(to_bytes(i.delegate_new_epoch_proof)) - .delegate_old_epoch_proof(to_bytes(i.delegate_old_epoch_proof)) - .delegate_infos( - DelegateInfos::new_builder() - .extend(i.delegate_infos.into_iter().map(|d| { - DelegateInfo::new_builder() - .delegator_addr(to_identity(&d.delegator_addr)) - .amount(to_uint128(d.amount)) - .build() - })) - .build(), - ) - .build() - })) - .build(), - ) - .build(); - - let input_type = DelegateSmtWitness::new_builder() - .mode(0.into()) - .update_info(delegate_update_infos) - .build(); + pub fn witness(mode: u8) -> WitnessArgs { + let lock_field = DelegateAtWitness::new_builder().mode(mode.into()).build(); + + if mode == 0 { // staker unlock + // todo: eth sig placeholder + } + + WitnessArgs::new_builder() + .lock(Some(lock_field.as_bytes()).pack()) + .build() + } + + pub fn smt_witness(mode: u8, all_stake_group_infos: Vec) -> WitnessArgs { + let type_field = ADelegateSmtWitness::from(DelegateSmtWitness { + mode, + update_info: DelegateSmtUpdateInfo { + all_stake_group_infos, + }, + }); + WitnessArgs::new_builder() - .input_type(Some(input_type.as_bytes()).pack()) + .input_type(Some(type_field.as_bytes()).pack()) .build() } } diff --git a/tx-builder/src/ckb/helper/stake.rs b/tx-builder/src/ckb/helper/stake.rs index f671ec1..7d4a74e 100644 --- a/tx-builder/src/ckb/helper/stake.rs +++ b/tx-builder/src/ckb/helper/stake.rs @@ -6,14 +6,14 @@ use ckb_types::{H160, H256}; use common::traits::ckb_rpc_client::CkbRpc; use common::types::axon_types::stake::{ - StakeArgs, StakeAtWitness, StakeInfoBuilder, StakeInfoDelta, StakeInfos, StakeSmtUpdateInfo, - StakeSmtWitness, + StakeArgs, StakeAtWitness, StakeInfoDelta, StakeSmtWitness as AStakeSmtWitness, }; use common::types::ckb_rpc_client::Cell; use common::types::tx_builder::{NetworkType, StakeItem}; use common::utils::convert::*; -use crate::ckb::define::{scripts::*, types::StakeInfo}; +use crate::ckb::define::scripts::*; +use crate::ckb::define::types::{StakeInfo, StakeSmtUpdateInfo, StakeSmtWitness}; use crate::ckb::helper::ckb::cell_collector::{get_cell_by_scripts, get_cell_by_type}; use crate::ckb::helper::metadata::Metadata; use crate::ckb::helper::unique_cell_dep; @@ -95,14 +95,6 @@ impl Stake { unique_cell_dep(ckb_rpc, Self::smt_type(type_id)).await } - // todo: eth sig placeholder - pub fn witness_placeholder(mode: u8) -> WitnessArgs { - let lock_field = StakeAtWitness::new_builder().mode(mode.into()).build(); - WitnessArgs::new_builder() - .lock(Some(lock_field.as_bytes()).pack()) - .build() - } - pub fn item(stake: &StakeInfoDelta) -> StakeItem { StakeItem { is_increase: to_bool(&stake.is_increase()), @@ -123,30 +115,34 @@ impl Stake { get_cell_by_type(ckb_rpc, delegate_smt_type).await } + pub fn witness(mode: u8) -> WitnessArgs { + let lock_field = StakeAtWitness::new_builder().mode(mode.into()).build(); + + if mode == 0 { // staker unlock + // todo: eth sig placeholder + } + + WitnessArgs::new_builder() + .lock(Some(lock_field.as_bytes()).pack()) + .build() + } + pub fn smt_witness( + mode: u8, all_stake_infos: Vec, - old_proof: Vec, - new_proof: Vec, + old_epoch_proof: Vec, + new_epoch_proof: Vec, ) -> WitnessArgs { - let stake_infos = StakeInfos::new_builder() - .extend(all_stake_infos.into_iter().map(|s| { - StakeInfoBuilder::default() - .addr(to_identity(&s.addr)) - .amount(to_uint128(s.amount)) - .build() - })) - .build(); - let updates = StakeSmtUpdateInfo::new_builder() - .all_stake_infos(stake_infos) - .old_epoch_proof(to_bytes(old_proof)) - .new_epoch_proof(to_bytes(new_proof)) - .build(); - let input_type = StakeSmtWitness::new_builder() - .mode(0.into()) - .update_info(updates) - .build(); + let type_field = AStakeSmtWitness::from(StakeSmtWitness { + mode, + update_info: StakeSmtUpdateInfo { + all_stake_infos, + old_epoch_proof, + new_epoch_proof, + }, + }); WitnessArgs::new_builder() - .input_type(Some(input_type.as_bytes()).pack()) + .input_type(Some(type_field.as_bytes()).pack()) .build() } } diff --git a/tx-builder/src/ckb/helper/withdraw.rs b/tx-builder/src/ckb/helper/withdraw.rs index 3783002..8864241 100644 --- a/tx-builder/src/ckb/helper/withdraw.rs +++ b/tx-builder/src/ckb/helper/withdraw.rs @@ -1,10 +1,10 @@ use anyhow::Result; -use ckb_types::packed::{CellDep, OutPoint, Script}; +use ckb_types::packed::{CellDep, OutPoint, Script, WitnessArgs}; use ckb_types::prelude::{Builder, Entity, Pack}; use ckb_types::{H160, H256}; use common::traits::ckb_rpc_client::CkbRpc; -use common::types::axon_types::withdraw::WithdrawArgs; +use common::types::axon_types::withdraw::{WithdrawArgs, WithdrawWitness}; use common::types::ckb_rpc_client::Cell; use common::types::tx_builder::NetworkType; use common::types::{ @@ -73,6 +73,19 @@ impl Withdraw { get_cell_by_scripts(ckb_rpc, withdraw_lock, xudt).await } + pub fn witness(kicker_unlock: bool) -> WitnessArgs { + if kicker_unlock { + WitnessArgs::new_builder().build() + } else { + let lock_field = WithdrawWitness::new_builder() + .signature(to_bytes(vec![0u8; 65])) + .build(); + WitnessArgs::new_builder() + .lock(Some(lock_field.as_bytes()).pack()) + .build() + } + } + pub fn update_cell_data( withdraw_cell: Cell, inaugration_epoch: Epoch, diff --git a/tx-builder/src/ckb/init.rs b/tx-builder/src/ckb/init.rs index 09b6286..7d0a811 100644 --- a/tx-builder/src/ckb/init.rs +++ b/tx-builder/src/ckb/init.rs @@ -1,6 +1,6 @@ use anyhow::Result; use async_trait::async_trait; -use ckb_sdk::unlock::{InfoCellData, ScriptSigner}; +use ckb_sdk::unlock::InfoCellData; use ckb_sdk::{ScriptGroup, ScriptGroupType}; use ckb_types::H160; use ckb_types::{ @@ -28,8 +28,8 @@ use crate::ckb::define::types::{ DelegateSmtCellData, MetadataCellData, RewardSmtCellData, StakeSmtCellData, }; use crate::ckb::helper::{ - AlwaysSuccess, Checkpoint as HCheckpoint, Delegate, Metadata as HMetadata, OmniEth, Secp256k1, - Selection, Stake, Tx, TypeId, Xudt, + AlwaysSuccess, Checkpoint as HCheckpoint, Delegate, Metadata as HMetadata, OmniEth, Reward, + Secp256k1, Selection, Stake, Tx, TypeId, Xudt, }; use crate::ckb::NETWORK_TYPE; @@ -110,7 +110,7 @@ impl<'a, C: CkbRpc> IInitTxBuilder<'a, C> for InitTxBuilder<'a, C> { HMetadata::type_dep(), Stake::smt_type_dep(), Delegate::smt_type_dep(), - // Reward::smt_type_dep(), + Reward::smt_type_dep(), ]; let witnesses = vec![ @@ -125,19 +125,20 @@ impl<'a, C: CkbRpc> IInitTxBuilder<'a, C> for InitTxBuilder<'a, C> { .witnesses(witnesses.pack()) .build(); - let tx = Tx::new(self.ckb, tx).balance(seeder_lock.clone()).await?; + let mut tx = Tx::new(self.ckb, tx); + tx.balance(seeder_lock.clone()).await?; - let (tx, type_id_args) = self.modify_outputs(tx, omni_eth.address()?)?; + let (tx_view, type_id_args) = self.modify_outputs(tx.inner_ref(), omni_eth.address()?)?; + tx.set_tx(tx_view); - let signer = omni_eth.signer()?; - let tx = signer.sign_tx(&tx, &ScriptGroup { + tx.sign(&omni_eth.signer()?, &ScriptGroup { script: seeder_lock, group_type: ScriptGroupType::Lock, input_indices: vec![0], output_indices: vec![], })?; - Ok((tx, type_id_args)) + Ok((tx.inner(), type_id_args)) } } @@ -167,7 +168,7 @@ impl<'a, C: CkbRpc> InitTxBuilder<'a, C> { fn modify_outputs( &self, - tx: TransactionView, + tx: &TransactionView, seeder_addr: H160, ) -> Result<(TransactionView, TypeIds)> { let mut outputs = tx.outputs().into_iter().collect::>(); @@ -199,11 +200,13 @@ impl<'a, C: CkbRpc> InitTxBuilder<'a, C> { // metadata cell let metadata_type_id = TypeId::calc(&first_input, 3); + let metadata_type = HMetadata::type_(&metadata_type_id); + let metadata_type_hash = metadata_type.calc_script_hash(); outputs[3] = tx .output(3) .unwrap() .as_builder() - .type_(Some(HMetadata::type_(&metadata_type_id)).pack()) + .type_(Some(metadata_type).pack()) .build(); // stake smt cell @@ -274,7 +277,7 @@ impl<'a, C: CkbRpc> InitTxBuilder<'a, C> { issue_type_id, selection_type_id, checkpoint_type_id, - metadata_type_id: metadata_type_id.clone(), + metadata_type_id, reward_smt_type_id, stake_smt_type_id, delegate_smt_type_id, @@ -324,7 +327,7 @@ impl<'a, C: CkbRpc> InitTxBuilder<'a, C> { // stake smt cell data outputs_data[4] = AStakeSmtCellData::from(StakeSmtCellData { - metadata_type_id: metadata_type_id.clone(), + metadata_type_hash: metadata_type_hash.clone(), ..Default::default() }) .as_bytes() @@ -332,7 +335,7 @@ impl<'a, C: CkbRpc> InitTxBuilder<'a, C> { // delegate smt cell data outputs_data[5] = ADelegateSmtCellData::from(DelegateSmtCellData { - metadata_type_id: metadata_type_id.clone(), + metadata_type_hash: metadata_type_hash.clone(), ..Default::default() }) .as_bytes() @@ -340,7 +343,7 @@ impl<'a, C: CkbRpc> InitTxBuilder<'a, C> { // reward smt cell data outputs_data[6] = ARewardSmtCellData::from(RewardSmtCellData { - metadata_type_id, + metadata_type_hash, ..Default::default() }) .as_bytes() diff --git a/tx-builder/src/ckb/metadata.rs b/tx-builder/src/ckb/metadata.rs index 02a75d8..61a4be1 100644 --- a/tx-builder/src/ckb/metadata.rs +++ b/tx-builder/src/ckb/metadata.rs @@ -7,6 +7,7 @@ use ckb_types::{ packed::{CellInput, CellOutput, Script}, prelude::{Entity, Pack}, }; +use ethereum_types::H160; use common::traits::{ ckb_rpc_client::CkbRpc, @@ -19,9 +20,9 @@ use common::types::axon_types::{ withdraw::WithdrawAtCellData as AWithdrawAtCellData, }; use common::types::tx_builder::*; -use ethereum_types::H160; use crate::ckb::define::types::*; +use crate::ckb::helper::Metadata as HMetadata; pub struct MetadataSmtTxBuilder<'a, C: CkbRpc, PSmt> { _ckb: &'a C, @@ -317,13 +318,15 @@ where metadata_cell_data.metadata.push(new_metadata); let _stake_smt_cell_data = StakeSmtCellData { - smt_root: Into::<[u8; 32]>::into(new_stake_root).into(), - metadata_type_id: metadata_cell_data.type_ids.metadata_type_id.clone(), + smt_root: Into::<[u8; 32]>::into(new_stake_root).into(), + metadata_type_hash: HMetadata::type_(&metadata_cell_data.type_ids.metadata_type_id) + .calc_script_hash(), }; let _delegate_smt_cell_data = DelegateSmtCellData { - smt_roots: delegator_staker_smt_roots, - metadata_type_id: metadata_cell_data.type_ids.metadata_type_id.clone(), + smt_roots: delegator_staker_smt_roots, + metadata_type_hash: HMetadata::type_(&metadata_cell_data.type_ids.metadata_type_id) + .calc_script_hash(), }; let mut withdraw_set: HashMap = HashMap::default(); diff --git a/tx-builder/src/ckb/mint.rs b/tx-builder/src/ckb/mint.rs index b611ad7..c784cdd 100644 --- a/tx-builder/src/ckb/mint.rs +++ b/tx-builder/src/ckb/mint.rs @@ -1,6 +1,5 @@ use anyhow::Result; use async_trait::async_trait; -use ckb_sdk::unlock::ScriptSigner; use ckb_sdk::{ScriptGroup, ScriptGroupType}; use ckb_types::{ bytes::Bytes, @@ -88,23 +87,24 @@ impl<'a, C: CkbRpc> IMintTxBuilder<'a, C> for MintTxBuilder<'a, C> { .witnesses(witnesses.pack()) .build(); - let tx = Tx::new(self.ckb, tx).balance(seeder_lock.clone()).await?; + let mut tx = Tx::new(self.ckb, tx); + tx.balance(seeder_lock.clone()).await?; let signer = OmniEth::new(self.seeder_key.clone()).signer()?; - let tx = signer.sign_tx(&tx, &ScriptGroup { + tx.sign(&signer, &ScriptGroup { script: seeder_lock.clone(), group_type: ScriptGroupType::Lock, input_indices: vec![1], output_indices: vec![], })?; - let tx = signer.sign_tx(&tx, &ScriptGroup { - script: seeder_lock, + tx.sign(&signer, &ScriptGroup { + script: seeder_lock.clone(), group_type: ScriptGroupType::Lock, input_indices: vec![2], output_indices: vec![], })?; - Ok(tx) + Ok(tx.inner()) } } diff --git a/tx-builder/src/ckb/reward.rs b/tx-builder/src/ckb/reward.rs index a605e51..d5d4611 100644 --- a/tx-builder/src/ckb/reward.rs +++ b/tx-builder/src/ckb/reward.rs @@ -5,7 +5,7 @@ use async_trait::async_trait; use ckb_types::{ bytes::Bytes, core::{Capacity, TransactionBuilder, TransactionView}, - packed::{CellDep, CellInput, CellOutput, Script}, + packed::{CellDep, CellInput, CellOutput, Script, WitnessArgs}, prelude::{Entity, Pack}, H160, }; @@ -136,8 +136,11 @@ where ]; let mut witnesses = vec![ - ARewardWitness::from(reward_witness).as_bytes(), // reward cell lock & type - bytes::Bytes::default(), // selection cell lock & type + WitnessArgs::new_builder() + .input_type(Some(ARewardWitness::from(reward_witness).as_bytes()).pack()) + .build() + .as_bytes(), + bytes::Bytes::default(), // selection cell lock & type ]; if token_amount.is_some() { witnesses.push(OmniEth::witness_placeholder().as_bytes()); // AT cell lock @@ -152,11 +155,10 @@ where .witnesses(witnesses.pack()) .build(); - let tx = Tx::new(self.ckb, tx) - .balance(self.token_lock.clone()) - .await?; + let mut tx = Tx::new(self.ckb, tx); + tx.balance(self.token_lock.clone()).await?; - Ok(tx) + Ok(tx.inner()) } } @@ -337,8 +339,9 @@ where vec![ // reward smt cell data ARewardSmtCellData::from(RewardSmtCellData { - claim_smt_root: reward_smt_root, - metadata_type_id: self.type_ids.metadata_type_id.clone(), + claim_smt_root: reward_smt_root, + metadata_type_hash: Reward::smt_type(&self.type_ids.metadata_type_id) + .calc_script_hash(), }) .as_bytes(), // AT cell data diff --git a/tx-builder/src/ckb/stake.rs b/tx-builder/src/ckb/stake.rs index 01151a4..02f8b81 100644 --- a/tx-builder/src/ckb/stake.rs +++ b/tx-builder/src/ckb/stake.rs @@ -130,11 +130,10 @@ impl<'a, C: CkbRpc> StakeTxBuilder<'a, C> { .witnesses(witnesses.pack()) .build(); - let tx = Tx::new(self.ckb, tx) - .balance(self.token_lock.clone()) - .await?; + let mut tx = Tx::new(self.ckb, tx); + tx.balance(self.token_lock.clone()).await?; - Ok(tx) + Ok(tx.inner()) } async fn build_update_stake_tx(&self, stake_cell: Cell) -> Result { @@ -173,9 +172,9 @@ impl<'a, C: CkbRpc> StakeTxBuilder<'a, C> { ]; let witnesses = vec![ - Stake::witness_placeholder(0u8).as_bytes(), // stake AT cell lock, todo - OmniEth::witness_placeholder().as_bytes(), // AT cell lock - OmniEth::witness_placeholder().as_bytes(), // capacity provider lock + Stake::witness(0u8).as_bytes(), // stake AT cell lock, todo + OmniEth::witness_placeholder().as_bytes(), // AT cell lock + OmniEth::witness_placeholder().as_bytes(), // capacity provider lock ]; let tx = TransactionBuilder::default() @@ -186,11 +185,10 @@ impl<'a, C: CkbRpc> StakeTxBuilder<'a, C> { .witnesses(witnesses.pack()) .build(); - let tx = Tx::new(self.ckb, tx) - .balance(self.token_lock.clone()) - .await?; + let mut tx = Tx::new(self.ckb, tx); + tx.balance(self.token_lock.clone()).await?; - Ok(tx) + Ok(tx.inner()) } async fn add_token_to_inputs(&self, inputs: &mut Vec) -> Result { diff --git a/tx-builder/src/ckb/stake_smt.rs b/tx-builder/src/ckb/stake_smt.rs index 4b42167..ac844b8 100644 --- a/tx-builder/src/ckb/stake_smt.rs +++ b/tx-builder/src/ckb/stake_smt.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use anyhow::Result; use async_trait::async_trait; +use ckb_sdk::{ScriptGroup, ScriptGroupType}; use ckb_types::{ bytes::Bytes, core::{Capacity, TransactionBuilder, TransactionView}, @@ -13,10 +14,8 @@ use molecule::prelude::Builder; use common::traits::{ ckb_rpc_client::CkbRpc, smt::StakeSmtStorage, tx_builder::IStakeSmtTxBuilder, }; -use common::types::axon_types::{ - basic::Byte32, - stake::{StakeArgs, StakeAtCellData, StakeAtWitness, StakeSmtCellData}, -}; +use common::types::axon_types::basic::Byte32; +use common::types::axon_types::stake::{StakeArgs, StakeAtCellData, StakeSmtCellData}; use common::types::ckb_rpc_client::Cell; use common::types::smt::{Root, Staker as SmtStaker, UserAmount}; use common::types::tx_builder::{ @@ -112,6 +111,8 @@ impl<'a, C: CkbRpc, S: StakeSmtStorage + Send + Sync> IStakeSmtTxBuilder<'a, C, ) .await?; + witnesses.push(OmniEth::witness_placeholder().as_bytes()); // capacity provider lock + let mut cell_deps = vec![ OmniEth::lock_dep(), Secp256k1::lock_dep(), @@ -135,12 +136,20 @@ impl<'a, C: CkbRpc, S: StakeSmtStorage + Send + Sync> IStakeSmtTxBuilder<'a, C, .witnesses(witnesses.pack()) .build(); - let kicker_lock = OmniEth::lock(&OmniEth::new(self.kicker.clone()).address()?); - let tx = Tx::new(self.ckb, tx).balance(kicker_lock).await?; + let omni_eth = OmniEth::new(self.kicker.clone()); + let kicker_lock = OmniEth::lock(&omni_eth.address()?); + + let mut tx = Tx::new(self.ckb, tx); + tx.balance(kicker_lock.clone()).await?; - // todo: sign tx + tx.sign(&omni_eth.signer()?, &ScriptGroup { + script: kicker_lock, + group_type: ScriptGroupType::Lock, + input_indices: vec![tx.inner_ref().inputs().len() - 1], + output_indices: vec![], + })?; - Ok((tx, statistics.non_top_stakers)) + Ok((tx.inner(), statistics.non_top_stakers)) } } @@ -168,7 +177,7 @@ impl<'a, C: CkbRpc, S: StakeSmtStorage + Send + Sync> StakeSmtTxBuilder<'a, C, S .build(), ); - witnesses.push(self.stake_at_witness().as_bytes()); + witnesses.push(Stake::witness(1).as_bytes()); let (old_total_stake_amount, old_stake_data) = self.parse_stake_data(stake_cell); @@ -190,7 +199,7 @@ impl<'a, C: CkbRpc, S: StakeSmtStorage + Send + Sync> StakeSmtTxBuilder<'a, C, S .previous_output(old_withdraw_cell.out_point.clone().into()) .build(), ); - witnesses.push(self.stake_at_witness().as_bytes()); + witnesses.push(Withdraw::witness(true).as_bytes()); ( old_total_stake_amount - withdraw_amount, @@ -212,7 +221,7 @@ impl<'a, C: CkbRpc, S: StakeSmtStorage + Send + Sync> StakeSmtTxBuilder<'a, C, S .as_builder() .delta( StakeItem { - is_increase: false, + is_increase: true, amount: 0, inauguration_epoch: 0, } @@ -249,13 +258,6 @@ impl<'a, C: CkbRpc, S: StakeSmtStorage + Send + Sync> StakeSmtTxBuilder<'a, C, S Ok(()) } - fn stake_at_witness(&self) -> WitnessArgs { - let stake_at_witness = StakeAtWitness::new_builder().mode(1.into()).build(); - WitnessArgs::new_builder() - .lock(Some(stake_at_witness.as_bytes()).pack()) - .build() - } - fn parse_stake_data(&self, cell: &Cell) -> (Amount, StakeAtCellData) { let mut cell_data_bytes = cell.output_data.clone().unwrap().into_bytes(); let total_stake_amount = new_u128(&cell_data_bytes[..TOKEN_BYTES]); @@ -274,7 +276,7 @@ impl<'a, C: CkbRpc, S: StakeSmtStorage + Send + Sync> StakeSmtTxBuilder<'a, C, S .collect(); self.stake_smt_storage - .insert(self.current_epoch + INAUGURATION, new_smt_stakers) + .insert(self.current_epoch, new_smt_stakers) .await?; self.stake_smt_storage.get_top_root().await @@ -297,8 +299,7 @@ impl<'a, C: CkbRpc, S: StakeSmtStorage + Send + Sync> StakeSmtTxBuilder<'a, C, S &StakeArgs::new_unchecked(cell.output.lock.args.as_bytes().to_owned().into()) .stake_addr() .as_bytes(), - ) - .unwrap(); + )?; let (_, stake_data) = self.parse_stake_data(&cell); let stake_delta = Stake::item(&stake_data.lock().delta()); @@ -359,10 +360,7 @@ impl<'a, C: CkbRpc, S: StakeSmtStorage + Send + Sync> StakeSmtTxBuilder<'a, C, S // get the old epoch proof for witness let old_epoch_proof = self .stake_smt_storage - .generate_sub_proof( - self.current_epoch + INAUGURATION, - old_smt.clone().into_keys().collect(), - ) + .generate_top_proof(vec![self.current_epoch]) .await?; let new_root = self.update_stake_smt(new_smt.clone()).await?; @@ -370,14 +368,12 @@ impl<'a, C: CkbRpc, S: StakeSmtStorage + Send + Sync> StakeSmtTxBuilder<'a, C, S // get the new epoch proof for witness let new_epoch_proof = self .stake_smt_storage - .generate_sub_proof( - self.current_epoch + INAUGURATION, - new_smt.clone().into_keys().collect(), - ) + .generate_top_proof(vec![self.current_epoch]) .await?; let stake_smt_witness = Stake::smt_witness( - new_smt + 0, + old_smt .into_iter() .map(|(addr, amount)| StakeInfo { addr: ckb_types::H160(addr.0), diff --git a/tx-builder/src/ckb/tests/mod.rs b/tx-builder/src/ckb/tests/mod.rs index 544301d..dfd866a 100644 --- a/tx-builder/src/ckb/tests/mod.rs +++ b/tx-builder/src/ckb/tests/mod.rs @@ -1,4 +1,2 @@ mod omni; -mod reward; -mod stake_smt; mod withdraw; diff --git a/tx-builder/src/ckb/tests/reward.rs b/tx-builder/src/ckb/tests/reward.rs deleted file mode 100644 index b8a5307..0000000 --- a/tx-builder/src/ckb/tests/reward.rs +++ /dev/null @@ -1,96 +0,0 @@ -#[cfg(test)] -mod tests { - use std::{path::PathBuf, vec}; - - use ckb_sdk::types::{ScriptGroup, ScriptGroupType}; - use ckb_sdk::unlock::ScriptSigner; - use ckb_types::h256; - - use common::traits::tx_builder::IRewardTxBuilder; - use common::types::tx_builder::{Epoch, RewardInfo, RewardTypeIds}; - use rpc_client::ckb_client::ckb_rpc_client::CkbRpcClient; - use storage::smt::SmtManager; - - use crate::ckb::helper::ckb::{OmniEth, Tx}; - use crate::ckb::reward::RewardTxBuilder; - - // #[tokio::test] - async fn _reward_tx(current_epoch: Epoch) { - let test_staker_key = - h256!("0x13b08bb054d5dd04013156dced8ba2ce4d8cc5973e10d905a228ea1abc267e62"); - let xudt_args = h256!("0xfdaf95d57c615deaed3d7307d3f649b88d50a51f592a428f3815768e5ae3eab3"); - let selection_type_id = - h256!("0xfdaf95d57c615deaed3d7307d3f649b88d50a51f592a428f3815768e5ae3eab3"); - let checkpoint_type_id = - h256!("0xfdaf95d57c615deaed3d7307d3f649b88d50a51f592a428f3815768e5ae3eab3"); - let metadata_type_id = - h256!("0xfdaf95d57c615deaed3d7307d3f649b88d50a51f592a428f3815768e5ae3eab3"); - let reward_smt_type_id = - h256!("0xfdaf95d57c615deaed3d7307d3f649b88d50a51f592a428f3815768e5ae3eab3"); - let stake_smt_type_id = - h256!("0xfdaf95d57c615deaed3d7307d3f649b88d50a51f592a428f3815768e5ae3eab3"); - let delegate_smt_type_id = - h256!("0xfdaf95d57c615deaed3d7307d3f649b88d50a51f592a428f3815768e5ae3eab3"); - let ckb_client = CkbRpcClient::new("https://testnet.ckb.dev"); - - let omni_eth = OmniEth::new(test_staker_key.clone()); - let staker_eth_addr = omni_eth.address().unwrap(); - let staker_ckb_addr = omni_eth.ckb_address().unwrap(); - println!("staker addr: {}", staker_ckb_addr); - - let staker_lock = OmniEth::lock(&staker_eth_addr); - - let path = PathBuf::from("./free-space/smt"); - let smt = SmtManager::new(path); - - let tx = RewardTxBuilder::new( - &ckb_client, - RewardTypeIds { - selection_type_id, - metadata_type_id, - checkpoint_type_id, - reward_smt_type_id, - stake_smt_type_id, - delegate_smt_type_id, - xudt_owner: xudt_args, - }, - smt, - RewardInfo { - base_reward: 10000, - half_reward_cycle: 100, - theoretical_propose_count: 10, - epoch_count: 10, - }, - staker_eth_addr, - current_epoch, - ) - .build_tx() - .await - .unwrap(); - - println!("tx: {}", tx); - - let signer = omni_eth.signer().unwrap(); - let tx = signer - .sign_tx(&tx, &ScriptGroup { - script: staker_lock.clone(), - group_type: ScriptGroupType::Lock, - input_indices: vec![1], - output_indices: vec![0], - }) - .unwrap(); - let tx = signer - .sign_tx(&tx, &ScriptGroup { - script: staker_lock, - group_type: ScriptGroupType::Lock, - input_indices: vec![2], - output_indices: vec![0], - }) - .unwrap(); - - match Tx::new(&ckb_client, tx).send().await { - Ok(tx_hash) => println!("tx hash: 0x{}", tx_hash), - Err(e) => println!("{}", e), - } - } -} diff --git a/tx-builder/src/ckb/tests/stake_smt.rs b/tx-builder/src/ckb/tests/stake_smt.rs deleted file mode 100644 index 3080230..0000000 --- a/tx-builder/src/ckb/tests/stake_smt.rs +++ /dev/null @@ -1,48 +0,0 @@ -#[cfg(test)] -mod tests { - use ckb_types::h256; - - use common::traits::tx_builder::IStakeSmtTxBuilder; - use common::types::tx_builder::StakeSmtTypeIds; - use rpc_client::ckb_client::ckb_rpc_client::CkbRpcClient; - use storage::smt::SmtManager; - - use crate::ckb::stake_smt::StakeSmtTxBuilder; - - static _ROCKSDB_PATH: &str = "./free-space/smt"; - - // #[tokio::test] - async fn _stake_smt_tx() { - let smt_storage = SmtManager::new(_ROCKSDB_PATH); - let test_staker_key = - h256!("0x13b08bb054d5dd04013156dced8ba2ce4d8cc5973e10d905a228ea1abc267e62"); - let xudt_args = h256!("0xfdaf95d57c615deaed3d7307d3f649b88d50a51f592a428f3815768e5ae3eab3"); - let checkpoint_type_id = - h256!("0xfdaf95d57c615deaed3d7307d3f649b88d50a51f592a428f3815768e5ae3eab3"); - let metadata_type_id = - h256!("0xfdaf95d57c615deaed3d7307d3f649b88d50a51f592a428f3815768e5ae3eab3"); - let stake_smt_type_id = - h256!("0xfdaf95d57c615deaed3d7307d3f649b88d50a51f592a428f3815768e5ae3eab3"); - let ckb_client = CkbRpcClient::new("https://testnet.ckb.dev"); - - let (tx, _) = StakeSmtTxBuilder::new( - &ckb_client, - test_staker_key, - 1, - StakeSmtTypeIds { - metadata_type_id, - stake_smt_type_id, - checkpoint_type_id, - xudt_owner: xudt_args, - }, - 10, - vec![], - smt_storage, - ) - .build_tx() - .await - .unwrap(); - - println!("tx: {}", tx); - } -} diff --git a/tx-builder/src/ckb/withdraw.rs b/tx-builder/src/ckb/withdraw.rs index e376e86..30b851c 100644 --- a/tx-builder/src/ckb/withdraw.rs +++ b/tx-builder/src/ckb/withdraw.rs @@ -98,11 +98,10 @@ impl<'a, C: CkbRpc> IWithdrawTxBuilder<'a, C> for WithdrawTxBuilder<'a, C> { .witnesses(witnesses.pack()) .build(); - let tx = Tx::new(self.ckb, tx) - .balance(self.token_lock.clone()) - .await?; + let mut tx = Tx::new(self.ckb, tx); + tx.balance(self.token_lock.clone()).await?; - Ok(tx) + Ok(tx.inner()) } }