diff --git a/examples/counter/settings/Devnet.toml b/examples/counter/settings/Devnet.toml index 33d49de37..f08c936fa 100644 --- a/examples/counter/settings/Devnet.toml +++ b/examples/counter/settings/Devnet.toml @@ -3,70 +3,70 @@ name = "devnet" [accounts.deployer] mnemonic = "twice kind fence tip hidden tilt action fragile skin nothing glory cousin green tomorrow spring wrist shed math olympic multiply hip blue scout claw" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: 753b7cc01a1a2e86221266a154af739463fce51219d97e4f856cd7200c3bd2a601 # stx_address: ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM # btc_address: mqVnk6NPRdhntvfm4hh9vvjiRkFDUuSYsH [accounts.wallet_1] mnemonic = "sell invite acquire kitten bamboo drastic jelly vivid peace spawn twice guilt pave pen trash pretty park cube fragile unaware remain midnight betray rebuild" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: 7287ba251d44a4d3fd9276c88ce34c5c52a038955511cccaf77e61068649c17801 # stx_address: ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5 # btc_address: mr1iPkD9N3RJZZxXRk7xF9d36gffa6exNC [accounts.wallet_2] mnemonic = "hold excess usual excess ring elephant install account glad dry fragile donkey gaze humble truck breeze nation gasp vacuum limb head keep delay hospital" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: 530d9f61984c888536871c6573073bdfc0058896dc1adfe9a6a10dfacadc209101 # stx_address: ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG # btc_address: muYdXKmX9bByAueDe6KFfHd5Ff1gdN9ErG [accounts.wallet_3] mnemonic = "cycle puppy glare enroll cost improve round trend wrist mushroom scorpion tower claim oppose clever elephant dinosaur eight problem before frozen dune wagon high" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: d655b2523bcd65e34889725c73064feb17ceb796831c0e111ba1a552b0f31b3901 # stx_address: ST2JHG361ZXG51QTKY2NQCVBPPRRE2KZB1HR05NNC # btc_address: mvZtbibDAAA3WLpY7zXXFqRa3T4XSknBX7 [accounts.wallet_4] mnemonic = "board list obtain sugar hour worth raven scout denial thunder horse logic fury scorpion fold genuine phrase wealth news aim below celery when cabin" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: f9d7206a47f14d2870c163ebab4bf3e70d18f5d14ce1031f3902fbbc894fe4c701 # stx_address: ST2NEB84ASENDXKYGJPQW86YXQCEFEX2ZQPG87ND # btc_address: mg1C76bNTutiCDV3t9nWhZs3Dc8LzUufj8 [accounts.wallet_5] mnemonic = "hurry aunt blame peanut heavy update captain human rice crime juice adult scale device promote vast project quiz unit note reform update climb purchase" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: 3eccc5dac8056590432db6a35d52b9896876a3d5cbdea53b72400bc9c2099fe801 # stx_address: ST2REHHS5J3CERCRBEPMGH7921Q6PYKAADT7JP2VB # btc_address: mweN5WVqadScHdA81aATSdcVr4B6dNokqx [accounts.wallet_6] mnemonic = "area desk dutch sign gold cricket dawn toward giggle vibrant indoor bench warfare wagon number tiny universe sand talk dilemma pottery bone trap buddy" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: 7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01 # stx_address: ST3AM1A56AK2C1XAFJ4115ZSV26EB49BVQ10MGCS0 # btc_address: mzxXgV6e4BZSsz8zVHm3TmqbECt7mbuErt [accounts.wallet_7] mnemonic = "prevent gallery kind limb income control noise together echo rival record wedding sense uncover school version force bleak nuclear include danger skirt enact arrow" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401 # stx_address: ST3PF13W7Z0RRM42A8VZRVFQ75SV1K26RXEP8YGKJ # btc_address: n37mwmru2oaVosgfuvzBwgV2ysCQRrLko7 [accounts.wallet_8] mnemonic = "female adjust gallery certain visit token during great side clown fitness like hurt clip knife warm bench start reunion globe detail dream depend fortune" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: 6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01 # stx_address: ST3NBRSFKX28FQ2ZJ1MAKX58HKHSDGNV5N7R21XCP # btc_address: n2v875jbJ4RjBnTjgbfikDfnwsDV5iUByw [accounts.wallet_9] mnemonic = "shadow private easily thought say logic fault paddle word top book during ignore notable orange flight clock image wealth health outside kitten belt reform" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: de433bdfa14ec43aa1098d5be594c8ffb20a31485ff9de2923b2689471c401b801 # stx_address: STNHKEPYEPJ8ET55ZZ0M5A34J0R3N5FM2CMMMAZ6 # btc_address: mjSrB3wS4xab3kYqFktwBzfTdPg367ZJ2d diff --git a/src/generate/project.rs b/src/generate/project.rs index a67f6b5b9..eb5803b82 100644 --- a/src/generate/project.rs +++ b/src/generate/project.rs @@ -194,70 +194,70 @@ name = "devnet" [accounts.deployer] mnemonic = "twice kind fence tip hidden tilt action fragile skin nothing glory cousin green tomorrow spring wrist shed math olympic multiply hip blue scout claw" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: 753b7cc01a1a2e86221266a154af739463fce51219d97e4f856cd7200c3bd2a601 # stx_address: ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM # btc_address: mqVnk6NPRdhntvfm4hh9vvjiRkFDUuSYsH [accounts.wallet_1] mnemonic = "sell invite acquire kitten bamboo drastic jelly vivid peace spawn twice guilt pave pen trash pretty park cube fragile unaware remain midnight betray rebuild" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: 7287ba251d44a4d3fd9276c88ce34c5c52a038955511cccaf77e61068649c17801 # stx_address: ST1SJ3DTE5DN7X54YDH5D64R3BCB6A2AG2ZQ8YPD5 # btc_address: mr1iPkD9N3RJZZxXRk7xF9d36gffa6exNC [accounts.wallet_2] mnemonic = "hold excess usual excess ring elephant install account glad dry fragile donkey gaze humble truck breeze nation gasp vacuum limb head keep delay hospital" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: 530d9f61984c888536871c6573073bdfc0058896dc1adfe9a6a10dfacadc209101 # stx_address: ST2CY5V39NHDPWSXMW9QDT3HC3GD6Q6XX4CFRK9AG # btc_address: muYdXKmX9bByAueDe6KFfHd5Ff1gdN9ErG [accounts.wallet_3] mnemonic = "cycle puppy glare enroll cost improve round trend wrist mushroom scorpion tower claim oppose clever elephant dinosaur eight problem before frozen dune wagon high" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: d655b2523bcd65e34889725c73064feb17ceb796831c0e111ba1a552b0f31b3901 # stx_address: ST2JHG361ZXG51QTKY2NQCVBPPRRE2KZB1HR05NNC # btc_address: mvZtbibDAAA3WLpY7zXXFqRa3T4XSknBX7 [accounts.wallet_4] mnemonic = "board list obtain sugar hour worth raven scout denial thunder horse logic fury scorpion fold genuine phrase wealth news aim below celery when cabin" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: f9d7206a47f14d2870c163ebab4bf3e70d18f5d14ce1031f3902fbbc894fe4c701 # stx_address: ST2NEB84ASENDXKYGJPQW86YXQCEFEX2ZQPG87ND # btc_address: mg1C76bNTutiCDV3t9nWhZs3Dc8LzUufj8 [accounts.wallet_5] mnemonic = "hurry aunt blame peanut heavy update captain human rice crime juice adult scale device promote vast project quiz unit note reform update climb purchase" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: 3eccc5dac8056590432db6a35d52b9896876a3d5cbdea53b72400bc9c2099fe801 # stx_address: ST2REHHS5J3CERCRBEPMGH7921Q6PYKAADT7JP2VB # btc_address: mweN5WVqadScHdA81aATSdcVr4B6dNokqx [accounts.wallet_6] mnemonic = "area desk dutch sign gold cricket dawn toward giggle vibrant indoor bench warfare wagon number tiny universe sand talk dilemma pottery bone trap buddy" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: 7036b29cb5e235e5fd9b09ae3e8eec4404e44906814d5d01cbca968a60ed4bfb01 # stx_address: ST3AM1A56AK2C1XAFJ4115ZSV26EB49BVQ10MGCS0 # btc_address: mzxXgV6e4BZSsz8zVHm3TmqbECt7mbuErt [accounts.wallet_7] mnemonic = "prevent gallery kind limb income control noise together echo rival record wedding sense uncover school version force bleak nuclear include danger skirt enact arrow" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: b463f0df6c05d2f156393eee73f8016c5372caa0e9e29a901bb7171d90dc4f1401 # stx_address: ST3PF13W7Z0RRM42A8VZRVFQ75SV1K26RXEP8YGKJ # btc_address: n37mwmru2oaVosgfuvzBwgV2ysCQRrLko7 [accounts.wallet_8] mnemonic = "female adjust gallery certain visit token during great side clown fitness like hurt clip knife warm bench start reunion globe detail dream depend fortune" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: 6a1a754ba863d7bab14adbbc3f8ebb090af9e871ace621d3e5ab634e1422885e01 # stx_address: ST3NBRSFKX28FQ2ZJ1MAKX58HKHSDGNV5N7R21XCP # btc_address: n2v875jbJ4RjBnTjgbfikDfnwsDV5iUByw [accounts.wallet_9] mnemonic = "shadow private easily thought say logic fault paddle word top book during ignore notable orange flight clock image wealth health outside kitten belt reform" -balance = 1_000_000_000 +balance = 100_000_000_000_000 # secret_key: de433bdfa14ec43aa1098d5be594c8ffb20a31485ff9de2923b2689471c401b801 # stx_address: STNHKEPYEPJ8ET55ZZ0M5A34J0R3N5FM2CMMMAZ6 # btc_address: mjSrB3wS4xab3kYqFktwBzfTdPg367ZJ2d diff --git a/src/integrate/events_observer.rs b/src/integrate/events_observer.rs index 0c4ba6762..5b53b9596 100644 --- a/src/integrate/events_observer.rs +++ b/src/integrate/events_observer.rs @@ -1,4 +1,5 @@ use serde_json::Value; +use std::collections::BTreeMap; use std::error::Error; use std::path::PathBuf; use rocket::config::{Config, Environment, LoggingLevel}; @@ -7,12 +8,18 @@ use rocket::State; use std::str; use std::sync::mpsc::{Receiver, Sender}; use std::sync::{Arc, Mutex, RwLock}; -use crate::integrate::{BlockData, LogData, MempoolAdmissionData, ServiceStatusData, Status, Transaction}; -use crate::types::{ChainConfig, DevnetConfig}; +use crate::integrate::{BlockData, MempoolAdmissionData, ServiceStatusData, Status, Transaction}; +use crate::types::{self, AccountConfig, DevnetConfig}; +use crate::utils::stacks::{StacksRpc, transactions}; use crate::publish::{publish_contracts, Network}; use super::DevnetEvent; +use clarity_repl::clarity::types::{BuffData, TupleData, SequenceData, Value as ClarityValue}; +use clarity_repl::clarity::util::address::AddressHashMode; +use clarity_repl::clarity::util::hash::{hex_bytes, Hash160}; +use clarity_repl::clarity::representations::ClarityName; +use std::convert::TryFrom; -// decode request data +#[allow(dead_code)] #[derive(Deserialize)] pub struct NewBurnBlock { burn_block_hash: String, @@ -43,17 +50,26 @@ pub struct NewTransaction { #[derive(Clone, Debug)] pub struct EventObserverConfig { pub devnet_config: DevnetConfig, + pub accounts: BTreeMap, pub manifest_path: PathBuf, pub pox_info: PoxInfo, } #[derive(Deserialize, Debug, Clone, Default)] pub struct PoxInfo { + contract_id: String, pox_activation_threshold_ustx: u64, first_burnchain_block_height: u32, prepare_phase_block_length: u32, reward_phase_block_length: u32, reward_slots: u32, + total_liquid_supply_ustx: u64, + next_cycle: PoxCycle, +} + +#[derive(Deserialize, Debug, Clone, Default)] +pub struct PoxCycle { + min_threshold_ustx: u64, } pub async fn start_events_observer(events_config: EventObserverConfig, devnet_event_tx: Sender, terminator_rx: Receiver) -> Result<(), Box> { @@ -69,7 +85,7 @@ pub async fn start_events_observer(events_config: EventObserverConfig, devnet_ev rocket::custom(config) .manage(RwLock::new(events_config)) .manage(Arc::new(Mutex::new(devnet_event_tx.clone()))) - .mount("/", routes![handle_new_burn_block, handle_new_block, handle_new_mempool_tx, handle_drop_mempool_tx]) + .mount("/", routes![handle_new_burn_block, handle_new_block, handle_new_microblocks, handle_new_mempool_tx, handle_drop_mempool_tx]) .launch(); match terminator_rx.recv() { @@ -83,7 +99,7 @@ pub async fn start_events_observer(events_config: EventObserverConfig, devnet_ev } #[post("/new_burn_block", format = "application/json", data = "")] -pub fn handle_new_burn_block(config: State>, devnet_events_tx: State>>>, new_burn_block: Json) -> Json { +pub fn handle_new_burn_block(_config: State>, devnet_events_tx: State>>>, new_burn_block: Json) -> Json { let devnet_events_tx = devnet_events_tx.inner(); match devnet_events_tx.lock() { @@ -133,9 +149,7 @@ pub fn handle_new_block(config: State>, devnet_event let url = format!("http://0.0.0.0:{}/v2/pox", updated_config.devnet_config.stacks_node_rpc_port); updated_config.pox_info = match reqwest::blocking::get(url) { Ok(reponse) => { - let _ = tx.send(DevnetEvent::debug(format!("{:?}", reponse))); let pox_info: PoxInfo = reponse.json().unwrap(); - let _ = tx.send(DevnetEvent::debug(format!("{:?}", pox_info))); pox_info }, Err(_) => PoxInfo::default() @@ -146,8 +160,6 @@ pub fn handle_new_block(config: State>, devnet_event }; if let Some(updated_config) = updated_config { - let _ = tx.send(DevnetEvent::debug(format!("Updated config: {:?} ", updated_config.pox_info))); - let logs = match publish_contracts(updated_config.manifest_path.clone(), Network::Devnet) { Ok(res) => res.iter().map(|l| DevnetEvent::success(l.into())).collect(), Err(e) => vec![DevnetEvent::error(e.into())] @@ -182,6 +194,63 @@ pub fn handle_new_block(config: State>, devnet_event } }).collect(), })); + + // Every penultimate block, we check if some stacking orders should be submitted before the next + // cycle starts. + if new_block.burn_block_height % pox_cycle_length == (pox_cycle_length - 2) { + for pox_stacking_order in config_reader.devnet_config.pox_stacking_orders.iter() { + if pox_stacking_order.start_at_cycle == (pox_cycle_id + 1) { + + let account = match config_reader.accounts.get(&pox_stacking_order.wallet) { + None => continue, + Some(account) => account, + }; + let url = format!("http://0.0.0.0:{}", config_reader.devnet_config.stacks_node_rpc_port); + let stacks_rpc = StacksRpc::new(url); + let default_fee = 1000; + let nonce = stacks_rpc.get_nonce(account.address.to_string()) + .expect("Unable to retrieve nonce"); + + let stx_amount = config_reader.pox_info.next_cycle.min_threshold_ustx * pox_stacking_order.slots; + let (_, _, account_secret_keu) = types::compute_addresses( + &account.mnemonic, + &account.derivation, + account.is_mainnet); + let addr_bytes = Hash160([0u8; 20]); + let addr_version = AddressHashMode::SerializeP2PKH; + let stack_stx_tx = transactions::build_contrat_call_transaction( + config_reader.pox_info.contract_id.clone(), + "stack-stx".into(), + vec![ + ClarityValue::UInt(stx_amount.into()), + ClarityValue::Tuple( + TupleData::from_data(vec![ + ( + ClarityName::try_from("version".to_owned()).unwrap(), + ClarityValue::buff_from_byte(addr_version as u8), + ), + ( + ClarityName::try_from("hashbytes".to_owned()).unwrap(), + ClarityValue::Sequence(SequenceData::Buffer(BuffData { + data: addr_bytes.as_bytes().to_vec(), + })), + ), + ]) + .unwrap(), + ), + ClarityValue::UInt((new_block.burn_block_height - 1).into()), + ClarityValue::UInt(pox_stacking_order.duration.into()), + ], + nonce, + default_fee, + &hex_bytes(&account_secret_keu).unwrap() + ); + let _ = stacks_rpc.post_transaction(stack_stx_tx) + .expect("Unable to broadcast transaction"); + + } + } + } } }; @@ -192,7 +261,7 @@ pub fn handle_new_block(config: State>, devnet_event } #[post("/new_microblocks", format = "application/json")] -pub fn handle_new_microblocks(devnet_events_tx: State>>>) -> Json { +pub fn handle_new_microblocks(_devnet_events_tx: State>>>) -> Json { Json(json!({ "status": 200, "result": "Ok", @@ -200,7 +269,7 @@ pub fn handle_new_microblocks(devnet_events_tx: State>, devnet_events_tx: State>>>, raw_txs: Json>) -> Json { +pub fn handle_new_mempool_tx(_config: State>, devnet_events_tx: State>>>, raw_txs: Json>) -> Json { if let Ok(tx) = devnet_events_tx.lock() { for raw_tx in raw_txs.iter() { diff --git a/src/types/chain_config.rs b/src/types/chain_config.rs index d4f9369b3..cb8702979 100644 --- a/src/types/chain_config.rs +++ b/src/types/chain_config.rs @@ -134,7 +134,7 @@ pub struct PoxStackingOrder { pub start_at_cycle: u32, pub duration: u32, pub wallet: String, - pub slots: u32, + pub slots: u64, pub btc_address: String, } @@ -277,28 +277,28 @@ impl ChainConfig { stacks_explorer_image_url: devnet_config.stacks_explorer_image_url.take().unwrap_or(DEFAULT_STACKS_EXPLORER_IMAGE.to_string()), pox_stacking_orders: devnet_config.pox_stacking_orders.take().unwrap_or(vec![ PoxStackingOrder { - start_at_cycle: 0, + start_at_cycle: 3, duration: 12, wallet: "wallet_1".into(), slots: 2, btc_address: "mr1iPkD9N3RJZZxXRk7xF9d36gffa6exNC".into(), }, PoxStackingOrder { - start_at_cycle: 0, + start_at_cycle: 3, duration: 12, wallet: "wallet_2".into(), slots: 2, btc_address: "muYdXKmX9bByAueDe6KFfHd5Ff1gdN9ErG".into(), }, PoxStackingOrder { - start_at_cycle: 0, + start_at_cycle: 3, duration: 12, wallet: "wallet_3".into(), slots: 2, btc_address: "mvZtbibDAAA3WLpY7zXXFqRa3T4XSknBX7".into(), }, PoxStackingOrder { - start_at_cycle: 0, + start_at_cycle: 3, duration: 12, wallet: "wallet_4".into(), slots: 2, @@ -320,7 +320,7 @@ impl ChainConfig { } } -fn compute_addresses(mnemonic: &str, derivation_path: &str, mainnet: bool) -> (String, String, String) { +pub fn compute_addresses(mnemonic: &str, derivation_path: &str, mainnet: bool) -> (String, String, String) { let bip39_seed = match mnemonic::get_bip39_seed_from_mnemonic(&mnemonic, "") { diff --git a/src/types/mod.rs b/src/types/mod.rs index e93f86548..60e6be5a0 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -1,5 +1,5 @@ mod chain_config; mod project_config; -pub use chain_config::{ChainConfig, ChainConfigFile, DevnetConfig}; +pub use chain_config::{ChainConfig, ChainConfigFile, DevnetConfig, AccountConfig, compute_addresses}; pub use project_config::{ContractConfig, MainConfig, MainConfigFile, RequirementConfig}; diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 511000e24..92586e364 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -1,4 +1,5 @@ pub mod mnemonic; +pub mod stacks; use tokio;