Skip to content

Commit a1c18db

Browse files
committed
refactor: publish feature, shared with integrate
1 parent 9f47c73 commit a1c18db

File tree

2 files changed

+190
-208
lines changed

2 files changed

+190
-208
lines changed

src/frontend/cli.rs

Lines changed: 19 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,23 @@
1-
use std::collections::{BTreeMap, HashMap};
1+
use std::collections::HashMap;
22
use std::fs::{self, File};
33
use std::io::{prelude::*, BufReader, Read};
44
use std::path::PathBuf;
55
use std::{env, process};
66

77
use crate::poke::load_session;
88
use crate::integrate::{self, DevnetOrchestrator};
9+
use crate::publish::{self, Network, publish_contracts};
910
use crate::test::run_tests;
1011
use crate::types::{MainConfig, MainConfigFile, RequirementConfig};
1112
use crate::{
1213
generate::{
1314
self,
1415
changes::{Changes, TOMLEdition},
1516
},
16-
utils::mnemonic,
17-
};
18-
19-
use clarity_repl::clarity::codec::transaction::{
20-
StacksTransaction, StacksTransactionSigner, TransactionAnchorMode, TransactionAuth,
21-
TransactionPayload, TransactionPostConditionMode, TransactionPublicKeyEncoding,
22-
TransactionSmartContract, TransactionSpendingCondition,
23-
};
24-
use clarity_repl::clarity::codec::StacksMessageCodec;
25-
use clarity_repl::{
26-
clarity::{
27-
codec::{
28-
transaction::{
29-
RecoverableSignature, SinglesigHashMode, SinglesigSpendingCondition,
30-
TransactionVersion,
31-
},
32-
StacksString,
33-
},
34-
util::{
35-
address::AddressHashMode,
36-
secp256k1::{Secp256k1PrivateKey, Secp256k1PublicKey},
37-
StacksAddress,
38-
},
39-
},
40-
repl,
4117
};
18+
use clarity_repl::repl;
4219

4320
use clap::Clap;
44-
use secp256k1::{PublicKey, SecretKey};
45-
use tiny_hderive::bip32::ExtendedPrivKey;
4621
use toml;
4722

4823
#[derive(Clap)]
@@ -75,7 +50,7 @@ enum Command {
7550
/// Execute Clarinet Extension
7651
#[clap(name = "run")]
7752
Run(Run),
78-
/// Devnet subcommand
53+
/// Work on contracts integration
7954
#[clap(name = "integrate")]
8055
Integrate(Integrate),
8156
}
@@ -97,18 +72,12 @@ enum Contract {
9772
struct GenerateProject {
9873
/// Project's name
9974
pub name: String,
100-
/// Print debug info
101-
#[clap(short = 'd')]
102-
pub debug: bool,
10375
}
10476

10577
#[derive(Clap)]
10678
struct NewContract {
10779
/// Contract's name
10880
pub name: String,
109-
/// Print debug info
110-
#[clap(short = 'd')]
111-
pub debug: bool,
11281
/// Path to Clarinet.toml
11382
#[clap(long = "manifest-path")]
11483
pub manifest_path: Option<String>,
@@ -118,9 +87,6 @@ struct NewContract {
11887
struct LinkContract {
11988
/// Contract id
12089
pub contract_id: String,
121-
/// Print debug info
122-
#[clap(short = 'd')]
123-
pub debug: bool,
12490
/// Path to Clarinet.toml
12591
#[clap(long = "manifest-path")]
12692
pub manifest_path: Option<String>,
@@ -130,9 +96,6 @@ struct LinkContract {
13096
struct ForkContract {
13197
/// Contract id
13298
pub contract_id: String,
133-
/// Print debug info
134-
#[clap(short = 'd')]
135-
pub debug: bool,
13699
/// Path to Clarinet.toml
137100
#[clap(long = "manifest-path")]
138101
pub manifest_path: Option<String>,
@@ -143,29 +106,20 @@ struct ForkContract {
143106

144107
#[derive(Clap)]
145108
struct Poke {
146-
/// Print debug info
147-
#[clap(short = 'd')]
148-
pub debug: bool,
149109
/// Path to Clarinet.toml
150110
#[clap(long = "manifest-path")]
151111
pub manifest_path: Option<String>,
152112
}
153113

154114
#[derive(Clap)]
155115
struct Integrate {
156-
/// Print debug info
157-
#[clap(short = 'd')]
158-
pub debug: bool,
159116
/// Path to Clarinet.toml
160117
#[clap(long = "manifest-path")]
161118
pub manifest_path: Option<String>,
162119
}
163120

164121
#[derive(Clap)]
165122
struct Test {
166-
/// Print debug info
167-
#[clap(short = 'd')]
168-
pub debug: bool,
169123
/// Generate coverage
170124
#[clap(long = "coverage")]
171125
pub coverage: bool,
@@ -181,9 +135,6 @@ struct Test {
181135

182136
#[derive(Clap)]
183137
struct Run {
184-
/// Print debug info
185-
#[clap(short = 'd')]
186-
pub debug: bool,
187138
/// Script to run
188139
pub script: String,
189140
/// Path to Clarinet.toml
@@ -212,9 +163,6 @@ struct Publish {
212163

213164
#[derive(Clap)]
214165
struct Check {
215-
/// Print debug info
216-
#[clap(short = 'd')]
217-
pub debug: bool,
218166
/// Path to Clarinet.toml
219167
#[clap(long = "manifest-path")]
220168
pub manifest_path: Option<String>,
@@ -357,169 +305,32 @@ pub fn main() {
357305
}
358306
Command::Publish(deploy) => {
359307
let manifest_path = get_manifest_path_or_exit(deploy.manifest_path);
360-
let start_repl = false;
361-
let mode = if deploy.mocknet == true {
362-
"mocknet"
308+
309+
let network = if deploy.devnet == true {
310+
Network::Devnet
363311
} else if deploy.testnet == true {
364-
"testnet"
365-
} else {
312+
Network::Testnet
313+
} else if deploy.mainnet == true {
314+
// Network::Mainnet
366315
// TODO(ludo): before supporting mainnet deployments, we want to add a pass
367-
// making sure that addresses are consistent.
368-
panic!("Target deployment must be specified with --mocknet or --testnet")
369-
};
370-
let res = load_session(manifest_path, start_repl, mode.into());
371-
if let Err(e) = res {
372-
println!("{}", e);
373-
return;
374-
}
375-
let settings = res.unwrap();
376-
377-
let mut deployers_nonces = BTreeMap::new();
378-
let mut deployers_lookup = BTreeMap::new();
379-
for account in settings.initial_accounts.iter() {
380-
if account.name == "deployer" {
381-
deployers_lookup.insert("*", account.clone());
382-
}
383-
}
384-
385-
#[derive(Deserialize, Debug)]
386-
struct Balance {
387-
balance: String,
388-
nonce: u64,
389-
balance_proof: String,
390-
nonce_proof: String,
391-
}
392-
393-
let host = if mode == "mocknet" {
394-
"http://localhost:20443"
316+
// making sure that addresses are consistent + handle other hard coded flags.
317+
// Search for "mainnet handling".
318+
panic!("Target deployment must be specified with --devnet, --testnet, --mainnet")
395319
} else {
396-
"https://stacks-node-api.testnet.stacks.co"
320+
panic!("Target deployment must be specified with --devnet, --testnet, --mainnet")
321+
};
322+
match publish_contracts(manifest_path, network) {
323+
Ok(results) => println!("{}", results.join("\n")),
324+
Err(e) => println!("{}", e)
397325
};
398-
399-
for initial_contract in settings.initial_contracts.iter() {
400-
let contract_name = initial_contract.name.clone().unwrap();
401-
402-
let payload = TransactionSmartContract {
403-
name: contract_name.as_str().into(),
404-
code_body: StacksString::from_string(&initial_contract.code).unwrap(),
405-
};
406-
407-
let deployer = match deployers_lookup.get(contract_name.as_str()) {
408-
Some(deployer) => deployer,
409-
None => deployers_lookup.get("*").unwrap(),
410-
};
411-
412-
let bip39_seed =
413-
match mnemonic::get_bip39_seed_from_mnemonic(&deployer.mnemonic, "") {
414-
Ok(bip39_seed) => bip39_seed,
415-
Err(_) => panic!(),
416-
};
417-
let ext =
418-
ExtendedPrivKey::derive(&bip39_seed[..], deployer.derivation.as_str()).unwrap();
419-
let secret_key = SecretKey::parse_slice(&ext.secret()).unwrap();
420-
let public_key = PublicKey::from_secret_key(&secret_key);
421-
422-
let wrapped_public_key =
423-
Secp256k1PublicKey::from_slice(&public_key.serialize_compressed()).unwrap();
424-
let wrapped_secret_key = Secp256k1PrivateKey::from_slice(&ext.secret()).unwrap();
425-
426-
let anchor_mode = TransactionAnchorMode::Any;
427-
let tx_fee = 200 + initial_contract.code.len() as u64;
428-
429-
let nonce = match deployers_nonces.get(&deployer.name) {
430-
Some(nonce) => *nonce,
431-
None => {
432-
let request_url = format!(
433-
"{host}/v2/accounts/{addr}",
434-
host = host,
435-
addr = deployer.address,
436-
);
437-
438-
let response: Balance = reqwest::blocking::get(&request_url)
439-
.expect("Unable to retrieve account")
440-
.json()
441-
.expect("Unable to parse contract");
442-
let nonce = response.nonce;
443-
deployers_nonces.insert(deployer.name.clone(), nonce);
444-
nonce
445-
}
446-
};
447-
448-
let signer_addr = StacksAddress::from_public_keys(
449-
0,
450-
&AddressHashMode::SerializeP2PKH,
451-
1,
452-
&vec![wrapped_public_key],
453-
)
454-
.unwrap();
455-
456-
let spending_condition =
457-
TransactionSpendingCondition::Singlesig(SinglesigSpendingCondition {
458-
signer: signer_addr.bytes.clone(),
459-
nonce: nonce,
460-
tx_fee: tx_fee,
461-
hash_mode: SinglesigHashMode::P2PKH,
462-
key_encoding: TransactionPublicKeyEncoding::Compressed,
463-
signature: RecoverableSignature::empty(),
464-
});
465-
466-
let auth = TransactionAuth::Standard(spending_condition);
467-
let unsigned_tx = StacksTransaction {
468-
version: TransactionVersion::Testnet,
469-
chain_id: 0x80000000, // MAINNET=0x00000001
470-
auth: auth,
471-
anchor_mode: anchor_mode,
472-
post_condition_mode: TransactionPostConditionMode::Deny,
473-
post_conditions: vec![],
474-
payload: TransactionPayload::SmartContract(payload),
475-
};
476-
477-
let mut unsigned_tx_bytes = vec![];
478-
unsigned_tx
479-
.consensus_serialize(&mut unsigned_tx_bytes)
480-
.expect("FATAL: invalid transaction");
481-
482-
let mut tx_signer = StacksTransactionSigner::new(&unsigned_tx);
483-
tx_signer.sign_origin(&wrapped_secret_key).unwrap();
484-
let signed_tx = tx_signer.get_tx().unwrap();
485-
486-
let tx_bytes = signed_tx.serialize_to_vec();
487-
let client = reqwest::blocking::Client::new();
488-
let path = format!("{}/v2/transactions", host);
489-
let res = client
490-
.post(&path)
491-
.header("Content-Type", "application/octet-stream")
492-
.body(tx_bytes)
493-
.send()
494-
.unwrap();
495-
496-
if !res.status().is_success() {
497-
println!("{}", res.text().unwrap());
498-
panic!()
499-
}
500-
let txid: String = res.json().unwrap();
501-
502-
println!(
503-
"Deploying {} (txid: {}, nonce: {})",
504-
contract_name, txid, nonce
505-
);
506-
deployers_nonces.insert(deployer.name.clone(), nonce + 1);
507-
}
508-
// If mocknet, we should be pulling all the links.
509-
// Get ordered list of contracts
510-
// For each contract, get the nonce of the account deploying (if unknown)
511-
// Create a StacksTransaction with the contract, the name.
512-
// Sign the transaction
513-
// Send the transaction
514326
}
515327
Command::Integrate(cmd) => {
516328
let manifest_path = get_manifest_path_or_exit(cmd.manifest_path);
517329
println!(
518330
"Start orchestrating stacks-node, stacks-blockchain-api, bitcoind, bitcoin explorer, stacks-explorer"
519331
);
520332
let mut devnet = DevnetOrchestrator::new(manifest_path);
521-
let devnet_event_tx = devnet.event_tx.clone();
522-
integrate::run_devnet(&mut devnet);
333+
integrate::run_devnet(devnet);
523334
}
524335
};
525336
}

0 commit comments

Comments
 (0)