Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: add deploy subcommand #515

Merged
merged 4 commits into from
Nov 18, 2022
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 Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ rpassword = "3.0.2"
ipnetwork = "0.14"
multiaddr = { package = "parity-multiaddr", version = "0.4.0" }
byteorder = "1.3.2"
toml = "0.5.9"

tokio = { version = "1", features = ["net", "io-util", "rt"] }
futures = "0.3"
Expand Down
34 changes: 34 additions & 0 deletions src/deployment.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[[cells]]
name = "my_cell"
enable_type_id = true
location = { file = "build/release/my_cell" }

# reference to on-chain cells, this config is referenced by dep_groups.cells
[[cells]]
name = "genesis_cell"
enable_type_id = false
location = { tx_hash = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", index = 0 }

# Dep group cells
[[dep_groups]]
name = "my_dep_group"
cells = [
"my_cell",
"genesis_cell"
]

# The lock script set to output cells
[lock]
code_hash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8"
args = "0x0000000000000000000000000000000000000000"
hash_type = "type"

# For unlocking inputs with multisig lock script
[multisig_config]
sighash_addresses = [
"ckt1qyq111111111111111111111111111111111111111",
"ckt1qyq222222222222222222222222222222222222222",
"ckt1qyq333333333333333333333333333333333333333",
]
require_first_n = 1
threshold = 2
17 changes: 14 additions & 3 deletions src/interactive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ use ckb_signer::KeyStore;

use crate::plugin::PluginManager;
use crate::subcommands::{
AccountSubCommand, CliSubCommand, DAOSubCommand, MockTxSubCommand, MoleculeSubCommand,
PluginSubCommand, RpcSubCommand, SudtSubCommand, TxSubCommand, UtilSubCommand,
WalletSubCommand,
AccountSubCommand, CliSubCommand, DAOSubCommand, DeploySubCommand, MockTxSubCommand,
MoleculeSubCommand, PluginSubCommand, RpcSubCommand, SudtSubCommand, TxSubCommand,
UtilSubCommand, WalletSubCommand,
};
use crate::utils::{
completer::CkbCompleter,
Expand Down Expand Up @@ -382,6 +382,17 @@ impl InteractiveEnv {
output.print(format, color);
Ok(())
}
("deploy", Some(sub_matches)) => {
let genesis_info = self.genesis_info()?;
let output = DeploySubCommand::new(
&mut self.rpc_client,
&mut self.plugin_mgr,
genesis_info,
)
.process(sub_matches, debug)?;
output.print(format, color);
Ok(())
}
("exit", _) => {
return Ok(true);
}
Expand Down
15 changes: 12 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use clap::{App, AppSettings, Arg};
use interactive::InteractiveEnv;
use plugin::PluginManager;
use subcommands::{
AccountSubCommand, ApiServerSubCommand, CliSubCommand, DAOSubCommand, MockTxSubCommand,
MoleculeSubCommand, PluginSubCommand, PubSubCommand, RpcSubCommand, SudtSubCommand,
TxSubCommand, UtilSubCommand, WalletSubCommand,
AccountSubCommand, ApiServerSubCommand, CliSubCommand, DAOSubCommand, DeploySubCommand,
MockTxSubCommand, MoleculeSubCommand, PluginSubCommand, PubSubCommand, RpcSubCommand,
SudtSubCommand, TxSubCommand, UtilSubCommand, WalletSubCommand,
};
use utils::other::get_genesis_info;
use utils::{
Expand Down Expand Up @@ -163,6 +163,12 @@ fn main() -> Result<(), io::Error> {
.process(sub_matches, debug)
})
}
("deploy", Some(sub_matches)) => {
get_genesis_info(&None, &mut rpc_client).and_then(|genesis_info| {
DeploySubCommand::new(&mut rpc_client, &mut plugin_mgr, genesis_info)
.process(sub_matches, debug)
})
}
_ => {
if let Err(err) =
InteractiveEnv::from_config(ckb_cli_dir, config, plugin_mgr, key_store)
Expand Down Expand Up @@ -238,7 +244,9 @@ pub fn build_cli<'a>(version_short: &'a str, version_long: &'a str) -> App<'a> {
.subcommand(WalletSubCommand::subcommand())
.subcommand(DAOSubCommand::subcommand())
.subcommand(SudtSubCommand::subcommand("sudt"))
.subcommand(DeploySubCommand::subcommand("deploy"))
.arg(

Arg::with_name("url")
.long("url")
.takes_value(true)
Expand Down Expand Up @@ -344,4 +352,5 @@ You may also use some public available nodes, check the list of public nodes: ht
.subcommand(WalletSubCommand::subcommand())
.subcommand(DAOSubCommand::subcommand())
.subcommand(SudtSubCommand::subcommand("sudt"))
.subcommand(DeploySubCommand::subcommand("deploy"))
}
3 changes: 2 additions & 1 deletion src/plugin/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ use std::thread::{self, JoinHandle};
use bitcoin::util::bip32::DerivationPath;
use crossbeam_channel::bounded;

use ckb_sdk::util::serialize_signature;
use ckb_signer::{DerivedKeySet, Key, KeyStore, MasterPrivKey};
use ckb_types::core::service::Request;
use plugin_protocol::{JsonrpcError, KeyStoreRequest, PluginRequest, PluginResponse};

use super::manager::PluginHandler;
use crate::utils::other::{get_key_store, serialize_signature};
use crate::utils::other::get_key_store;
use crate::utils::rpc::JsonBytes;

pub const ERROR_KEYSTORE_REQUIRE_PASSWORD: &str = "keystore require password";
Expand Down
63 changes: 63 additions & 0 deletions src/subcommands/deploy/deployment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use ckb_jsonrpc_types as json_types;
use ckb_types::H256;
use serde_derive::{Deserialize, Serialize};

use crate::subcommands::tx::ReprMultisigConfig;

// Deployment
#[derive(Clone, Default, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub struct Deployment {
pub lock: json_types::Script,
pub cells: Vec<Cell>,
#[serde(default)]
pub dep_groups: Vec<DepGroup>,
#[serde(default)]
pub multisig_config: ReprMultisigConfig,
}

#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum CellLocation {
OutPoint { tx_hash: H256, index: u32 },
File { file: String },
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub struct Cell {
pub name: String,
pub location: CellLocation,
pub enable_type_id: bool,
}

#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub struct DepGroup {
pub name: String,
pub cells: Vec<String>,
}

// Recipe
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct CellRecipe {
pub name: String,
pub tx_hash: H256,
pub index: u32,
pub occupied_capacity: u64,
pub data_hash: H256,
pub type_id: Option<H256>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DepGroupRecipe {
pub name: String,
pub tx_hash: H256,
pub index: u32,
#[serde(default)]
pub data_hash: H256,
pub occupied_capacity: u64,
}

#[derive(Clone, Debug, Serialize, Deserialize, Default)]
pub struct DeploymentRecipe {
pub cell_recipes: Vec<CellRecipe>,
pub dep_group_recipes: Vec<DepGroupRecipe>,
}
71 changes: 71 additions & 0 deletions src/subcommands/deploy/intermedium_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use std::collections::HashMap;
use std::convert::TryFrom;

use anyhow::{Error, Result};
use ckb_jsonrpc_types as json_types;
use ckb_jsonrpc_types::JsonBytes;
use ckb_sdk::{unlock::MultisigConfig, NetworkType};
use ckb_types::{H160, H256};
use serde_derive::{Deserialize, Serialize};

use super::deployment::{Deployment, DeploymentRecipe};
use super::state_change::ReprStateChange;
use crate::subcommands::tx::{ReprMultisigConfig, ReprTxHelper};
use crate::utils::tx_helper::TxHelper;

#[derive(Clone, Default, Debug, Serialize, Deserialize)]
pub struct IntermediumInfo {
pub deployment: Deployment,
pub last_recipe: Option<DeploymentRecipe>,
pub new_recipe: DeploymentRecipe,
// For offline sign (should verify the tx hash)
pub used_input_txs: HashMap<H256, json_types::Transaction>,
pub cell_tx: Option<json_types::Transaction>,
pub cell_tx_signatures: HashMap<JsonBytes, Vec<JsonBytes>>,
pub cell_changes: Vec<ReprStateChange>,
pub dep_group_tx: Option<json_types::Transaction>,
pub dep_group_tx_signatures: HashMap<JsonBytes, Vec<JsonBytes>>,
pub dep_group_changes: Vec<ReprStateChange>,
}

impl IntermediumInfo {
pub fn multisig_configs(&self) -> Result<HashMap<H160, ReprMultisigConfig>> {
// NOTE: we don't care the NetworkType here.
let network = NetworkType::Testnet;
let mut multisig_configs = HashMap::default();
if !self.deployment.multisig_config.sighash_addresses.is_empty() {
let config = MultisigConfig::try_from(self.deployment.multisig_config.clone())
.map_err(Error::msg)?;
multisig_configs.insert(config.hash160(), ReprMultisigConfig::new(config, network));
}
Ok(multisig_configs)
}

pub fn cell_tx_helper(&self) -> Result<Option<TxHelper>> {
if let Some(cell_tx) = self.cell_tx.as_ref() {
let repr = ReprTxHelper {
transaction: cell_tx.clone(),
multisig_configs: self.multisig_configs()?,
signatures: self.cell_tx_signatures.clone(),
};
let helper = TxHelper::try_from(repr).map_err(Error::msg)?;
Ok(Some(helper))
} else {
Ok(None)
}
}

pub fn dep_group_tx_helper(&self) -> Result<Option<TxHelper>> {
if let Some(dep_group_tx) = self.dep_group_tx.as_ref() {
let repr = ReprTxHelper {
transaction: dep_group_tx.clone(),
multisig_configs: self.multisig_configs()?,
signatures: self.dep_group_tx_signatures.clone(),
};
let helper = TxHelper::try_from(repr).map_err(Error::msg)?;
Ok(Some(helper))
} else {
Ok(None)
}
}
}
Loading