validator.rs 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2022 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::{collections::HashMap, io::Cursor};
  19. use async_std::sync::{Arc, RwLock};
  20. use darkfi_sdk::{
  21. crypto::{
  22. constants::MERKLE_DEPTH,
  23. schnorr::{SchnorrPublic, SchnorrSecret},
  24. ContractId, MerkleNode, PublicKey,
  25. },
  26. db::ZKAS_DB_NAME,
  27. };
  28. use darkfi_serial::{deserialize, serialize, Decodable, Encodable, WriteExt};
  29. use incrementalmerkletree::{bridgetree::BridgeTree, Tree};
  30. use log::{debug, error, info, warn};
  31. use pasta_curves::{group::ff::PrimeField, pallas};
  32. use rand::rngs::OsRng;
  33. use serde_json::json;
  34. use super::{
  35. constants,
  36. leadcoin::LeadCoin,
  37. state::{ConsensusState, Fork, SlotCheckpoint, StateCheckpoint},
  38. BlockInfo, BlockProposal, Header, LeadInfo, LeadProof,
  39. };
  40. use crate::{
  41. blockchain::Blockchain,
  42. rpc::jsonrpc::JsonNotification,
  43. runtime::vm_runtime::Runtime,
  44. system::{Subscriber, SubscriberPtr},
  45. tx::Transaction,
  46. util::time::Timestamp,
  47. wallet::WalletPtr,
  48. zk::{
  49. proof::{ProvingKey, VerifyingKey},
  50. vm::ZkCircuit,
  51. vm_stack::empty_witnesses,
  52. },
  53. zkas::ZkBinary,
  54. Error, Result,
  55. };
  56. /// Atomic pointer to validator state.
  57. pub type ValidatorStatePtr = Arc<RwLock<ValidatorState>>;
  58. /// This struct represents the state of a validator node.
  59. pub struct ValidatorState {
  60. /// Leader proof proving key
  61. pub lead_proving_key: Option<ProvingKey>,
  62. /// Leader proof verifying key
  63. pub lead_verifying_key: VerifyingKey,
  64. /// Hot/Live data used by the consensus algorithm
  65. pub consensus: ConsensusState,
  66. /// Canonical (finalized) blockchain
  67. pub blockchain: Blockchain,
  68. /// Pending transactions
  69. pub unconfirmed_txs: Vec<Transaction>,
  70. /// A map of various subscribers exporting live info from the blockchain
  71. /// TODO: Instead of JsonNotification, it can be an enum of internal objects,
  72. /// and then we don't have to deal with json in this module but only
  73. // externally.
  74. pub subscribers: HashMap<&'static str, SubscriberPtr<JsonNotification>>,
  75. /// ZK proof verifying keys for smart contract calls
  76. pub verifying_keys: Arc<RwLock<HashMap<[u8; 32], Vec<(String, VerifyingKey)>>>>,
  77. /// Wallet interface
  78. pub wallet: WalletPtr,
  79. }
  80. impl ValidatorState {
  81. pub async fn new(
  82. db: &sled::Db, // <-- TODO: Avoid this with some wrapping, sled should only be in blockchain
  83. genesis_ts: Timestamp,
  84. genesis_data: blake3::Hash,
  85. wallet: WalletPtr,
  86. faucet_pubkeys: Vec<PublicKey>,
  87. enable_participation: bool,
  88. ) -> Result<ValidatorStatePtr> {
  89. debug!("Initializing ValidatorState");
  90. debug!("Initializing wallet tables for consensus");
  91. // TODO: TESTNET: The stuff is kept entirely in memory for now, what should we write
  92. // to disk/wallet?
  93. //let consensus_tree_init_query = include_str!("../../script/sql/consensus_tree.sql");
  94. //let consensus_keys_init_query = include_str!("../../script/sql/consensus_keys.sql");
  95. //wallet.exec_sql(consensus_tree_init_query).await?;
  96. //wallet.exec_sql(consensus_keys_init_query).await?;
  97. debug!("Generating leader proof keys with k: {}", constants::LEADER_PROOF_K);
  98. let bincode = include_bytes!("../../proof/lead.zk.bin");
  99. let zkbin = ZkBinary::decode(bincode)?;
  100. let witnesses = empty_witnesses(&zkbin);
  101. let circuit = ZkCircuit::new(witnesses, zkbin);
  102. let lead_verifying_key = VerifyingKey::build(constants::LEADER_PROOF_K, &circuit);
  103. // We only need this proving key if we're going to participate in the consensus.
  104. let lead_proving_key = if enable_participation {
  105. Some(ProvingKey::build(constants::LEADER_PROOF_K, &circuit))
  106. } else {
  107. None
  108. };
  109. let blockchain = Blockchain::new(db, genesis_ts, genesis_data)?;
  110. let consensus = ConsensusState::new(blockchain.clone(), genesis_ts, genesis_data)?;
  111. let unconfirmed_txs = vec![];
  112. // -----NATIVE WASM CONTRACTS-----
  113. // This is the current place where native contracts are being deployed.
  114. // When the `Blockchain` object is created, it doesn't care whether it
  115. // already has the contract data or not. If there's existing data, it
  116. // will just open the necessary db and trees, and give back what it has.
  117. // This means that on subsequent runs our native contracts will already
  118. // be in a deployed state, so what we actually do here is a redeployment.
  119. // This kind of operation should only modify the contract's state in case
  120. // it wasn't deployed before (meaning the initial run). Otherwise, it
  121. // shouldn't touch anything, or just potentially update the db schemas or
  122. // whatever is necessary. This logic should be handled in the init function
  123. // of the actual contract, so make sure the native contracts handle this well.
  124. // FIXME: This ID should be something that does not solve the pallas curve equation,
  125. // and/or just hardcoded and forbidden in non-native contract deployment.
  126. let money_contract_id = ContractId::from(pallas::Base::from(u64::MAX - 420));
  127. // The faucet pubkeys are pubkeys which are allowed to create clear inputs
  128. // in the money contract.
  129. let money_contract_deploy_payload = serialize(&faucet_pubkeys);
  130. //let dao_contract_id = ContractId::from(pallas::Base::from(u64::MAX - 421));
  131. //let dao_contract_deploy_payload = vec![];
  132. // In this hashmap, we keep references to ZK proof verifying keys needed
  133. // for the circuits our native contracts provide.
  134. let mut verifying_keys = HashMap::new();
  135. let native_contracts = vec![
  136. (
  137. "Money Contract",
  138. money_contract_id,
  139. include_bytes!("../contract/money/money_contract.wasm").to_vec(),
  140. money_contract_deploy_payload,
  141. ),
  142. //(
  143. // "DAO Contract",
  144. // dao_contract_id,
  145. // include_bytes!("../contract/dao/dao_contract.wasm").to_vec(),
  146. // dao_contract_deploy_payload,
  147. //),
  148. ];
  149. info!("Deploying native wasm contracts");
  150. for nc in native_contracts {
  151. info!("Deploying {} with ContractID {}", nc.0, nc.1);
  152. let mut runtime = Runtime::new(&nc.2[..], blockchain.clone(), nc.1)?;
  153. runtime.deploy(&nc.3)?;
  154. info!("Successfully deployed {}", nc.0);
  155. // When deployed, we can do a lookup for the zkas circuits and
  156. // initialize verifying keys for them.
  157. info!("Creating ZK verifying keys for {} zkas circuits", nc.0);
  158. info!("Looking up zkas db for {} (ContractID: {})", nc.0, nc.1);
  159. let zkas_db = blockchain.contracts.lookup(&blockchain.sled_db, &nc.1, ZKAS_DB_NAME)?;
  160. let mut vks = vec![];
  161. for i in zkas_db.iter() {
  162. info!("Iterating over zkas db");
  163. let (zkas_ns, zkas_bincode) = i?;
  164. info!("Deserializing namespace");
  165. let zkas_ns: String = deserialize(&zkas_ns)?;
  166. info!("Creating VerifyingKey for zkas circuit with namespace {}", zkas_ns);
  167. let zkbin = ZkBinary::decode(&zkas_bincode)?;
  168. let circuit = ZkCircuit::new(empty_witnesses(&zkbin), zkbin);
  169. // FIXME: This k=13 man...
  170. let vk = VerifyingKey::build(13, &circuit);
  171. vks.push((zkas_ns, vk));
  172. }
  173. info!("Finished creating VerifyingKey objects for {} (ContractID: {})", nc.0, nc.1);
  174. verifying_keys.insert(nc.1.to_bytes(), vks);
  175. }
  176. info!("Finished deployment of native wasm contracts");
  177. // -----NATIVE WASM CONTRACTS-----
  178. // Here we initialize various subscribers that can export live consensus/blockchain data.
  179. let mut subscribers = HashMap::new();
  180. let block_subscriber = Subscriber::new();
  181. subscribers.insert("blocks", block_subscriber);
  182. let state = Arc::new(RwLock::new(ValidatorState {
  183. lead_proving_key,
  184. lead_verifying_key,
  185. consensus,
  186. blockchain,
  187. unconfirmed_txs,
  188. subscribers,
  189. verifying_keys: Arc::new(RwLock::new(verifying_keys)),
  190. wallet,
  191. }));
  192. Ok(state)
  193. }
  194. /// The node retrieves a transaction, validates its state transition,
  195. /// and appends it to the unconfirmed transactions list.
  196. pub async fn append_tx(&mut self, tx: Transaction) -> bool {
  197. let tx_hash = blake3::hash(&serialize(&tx));
  198. let tx_in_txstore = match self.blockchain.transactions.contains(&tx_hash) {
  199. Ok(v) => v,
  200. Err(e) => {
  201. error!("append_tx(): Failed querying txstore: {}", e);
  202. return false
  203. }
  204. };
  205. if self.unconfirmed_txs.contains(&tx) || tx_in_txstore {
  206. info!("append_tx(): We have already seen this tx.");
  207. return false
  208. }
  209. info!("append_tx(): Starting state transition validation");
  210. if let Err(e) = self.verify_transactions(&[tx.clone()], false).await {
  211. error!("append_tx(): Failed to verify transaction: {}", e);
  212. return false
  213. };
  214. info!("append_tx(): Appended tx to mempool");
  215. self.unconfirmed_txs.push(tx);
  216. true
  217. }
  218. /// Generate a block proposal for the current slot, containing all
  219. /// unconfirmed transactions. Proposal extends the longest fork
  220. /// chain the node is holding.
  221. pub fn propose(
  222. &mut self,
  223. idx: usize,
  224. sigma1: pallas::Base,
  225. sigma2: pallas::Base,
  226. ) -> Result<Option<(BlockProposal, LeadCoin)>> {
  227. let slot = self.consensus.current_slot();
  228. let (prev_hash, index) = self.consensus.longest_chain_last_hash().unwrap();
  229. let unproposed_txs = self.unproposed_txs(index);
  230. // TODO: [PLACEHOLDER] Create and add rewards transaction
  231. let mut tree = BridgeTree::<MerkleNode, MERKLE_DEPTH>::new(100);
  232. // The following is pretty weird, so something better should be done.
  233. for tx in &unproposed_txs {
  234. let mut hash = [0_u8; 32];
  235. hash[0..31].copy_from_slice(&blake3::hash(&serialize(tx)).as_bytes()[0..31]);
  236. tree.append(&MerkleNode::from(pallas::Base::from_repr(hash).unwrap()));
  237. }
  238. let root = tree.root(0).unwrap();
  239. // Checking if extending a fork or canonical
  240. let coin = if index == -1 {
  241. self.consensus.coins[idx]
  242. } else {
  243. self.consensus.forks[index as usize].sequence.last().unwrap().coins[idx]
  244. };
  245. // Generating leader proof
  246. let (proof, public_inputs) =
  247. coin.create_lead_proof(sigma1, sigma2, self.lead_proving_key.as_ref().unwrap());
  248. // Signing using coin
  249. let secret_key = coin.secret_key;
  250. let header = Header::new(
  251. prev_hash,
  252. self.consensus.slot_epoch(slot),
  253. slot,
  254. Timestamp::current_time(),
  255. root,
  256. );
  257. let signed_proposal = secret_key.sign(&mut OsRng, &header.headerhash().as_bytes()[..]);
  258. let public_key = PublicKey::from_secret(secret_key);
  259. let lead_info = LeadInfo::new(
  260. signed_proposal,
  261. public_key,
  262. public_inputs,
  263. coin.slot,
  264. coin.eta,
  265. LeadProof::from(proof?),
  266. self.consensus.get_current_offset(slot),
  267. *self.consensus.leaders_history.last().unwrap(),
  268. );
  269. Ok(Some((BlockProposal::new(header, unproposed_txs, lead_info), coin)))
  270. }
  271. /// Retrieve all unconfirmed transactions not proposed in previous blocks
  272. /// of provided index chain.
  273. pub fn unproposed_txs(&self, index: i64) -> Vec<Transaction> {
  274. let unproposed_txs = if index == -1 {
  275. // If index is -1 (canonical blockchain) a new fork will be generated,
  276. // therefore all unproposed transactions can be included in the proposal.
  277. self.unconfirmed_txs.clone()
  278. } else {
  279. // We iterate over the fork chain proposals to find already proposed
  280. // transactions and remove them from the local unproposed_txs vector.
  281. let mut filtered_txs = self.unconfirmed_txs.clone();
  282. let chain = &self.consensus.forks[index as usize];
  283. for state_checkpoint in &chain.sequence {
  284. for tx in &state_checkpoint.proposal.block.txs {
  285. if let Some(pos) = filtered_txs.iter().position(|txs| *txs == *tx) {
  286. filtered_txs.remove(pos);
  287. }
  288. }
  289. }
  290. filtered_txs
  291. };
  292. // Check if transactions exceed configured cap
  293. let cap = constants::TXS_CAP;
  294. if unproposed_txs.len() > cap {
  295. return unproposed_txs[0..cap].to_vec()
  296. }
  297. unproposed_txs
  298. }
  299. /// Given a proposal, the node verify its sender (slot leader) and finds which blockchain
  300. /// it extends. If the proposal extends the canonical blockchain, a new fork chain is created.
  301. pub async fn receive_proposal(
  302. &mut self,
  303. proposal: &BlockProposal,
  304. coin: Option<(usize, LeadCoin)>,
  305. ) -> Result<()> {
  306. let current = self.consensus.current_slot();
  307. // Node hasn't started participating
  308. match self.consensus.participating {
  309. Some(start) => {
  310. if current < start {
  311. return Ok(())
  312. }
  313. }
  314. None => return Ok(()),
  315. }
  316. // Node have already checked for finalization in this slot
  317. if current <= self.consensus.checked_finalization {
  318. warn!("receive_proposal(): Proposal received after finalization sync period.");
  319. return Err(Error::ProposalAfterFinalizationError)
  320. }
  321. // Proposal validations
  322. let lf = &proposal.block.lead_info;
  323. let hdr = &proposal.block.header;
  324. // Ignore proposal if not for current slot
  325. if hdr.slot != current {
  326. return Err(Error::ProposalNotForCurrentSlotError)
  327. }
  328. // Check if proposal extends any existing fork chains
  329. let index = self.consensus.find_extended_chain_index(proposal)?;
  330. if index == -2 {
  331. return Err(Error::ExtendedChainIndexNotFound)
  332. }
  333. // Check that proposal transactions don't exceed limit
  334. if proposal.block.txs.len() > constants::TXS_CAP {
  335. warn!(
  336. "receive_proposal(): Received proposal transactions exceed configured cap: {} - {}",
  337. proposal.block.txs.len(),
  338. constants::TXS_CAP
  339. );
  340. return Err(Error::ProposalTxsExceedCapError)
  341. }
  342. // Verify proposal signature is valid based on producer public key
  343. // TODO: derive public key from proof
  344. if !lf.public_key.verify(proposal.header.as_bytes(), &lf.signature) {
  345. warn!("receive_proposal(): Proposer {} signature could not be verified", lf.public_key);
  346. return Err(Error::InvalidSignature)
  347. }
  348. // Check if proposal hash matches actual one
  349. let proposal_hash = proposal.block.blockhash();
  350. if proposal.hash != proposal_hash {
  351. warn!(
  352. "receive_proposal(): Received proposal contains mismatched hashes: {} - {}",
  353. proposal.hash, proposal_hash
  354. );
  355. return Err(Error::ProposalHashesMissmatchError)
  356. }
  357. // Check if proposal header matches actual one
  358. let proposal_header = hdr.headerhash();
  359. if proposal.header != proposal_header {
  360. warn!(
  361. "receive_proposal(): Received proposal contains mismatched headers: {} - {}",
  362. proposal.header, proposal_header
  363. );
  364. return Err(Error::ProposalHeadersMissmatchError)
  365. }
  366. // Verify proposal offset
  367. let offset = self.consensus.get_current_offset(current);
  368. if offset != lf.offset {
  369. warn!(
  370. "receive_proposal(): Received proposal contains different offset: {} - {}",
  371. offset, lf.offset
  372. );
  373. return Err(Error::ProposalDifferentOffsetError)
  374. }
  375. // Verify proposal leader proof
  376. if let Err(e) = lf.proof.verify(&self.lead_verifying_key, &lf.public_inputs) {
  377. error!("receive_proposal(): Error during leader proof verification: {}", e);
  378. return Err(Error::LeaderProofVerification)
  379. };
  380. info!("receive_proposal(): Leader proof verified successfully!");
  381. // Validate proposal public value against coin creation slot checkpoint
  382. let checkpoint = self.consensus.get_slot_checkpoint(lf.coin_slot)?;
  383. if checkpoint.eta != lf.coin_eta {
  384. return Err(Error::ProposalDifferentCoinEtaError)
  385. }
  386. let (mu_y, mu_rho) = LeadCoin::election_seeds_u64(checkpoint.eta, checkpoint.slot);
  387. // y
  388. let prop_mu_y = lf.public_inputs[constants::PI_MU_Y_INDEX];
  389. if mu_y != prop_mu_y {
  390. error!(
  391. "receive_proposal(): Failed to verify mu_y: {:?}, proposed: {:?}",
  392. mu_y, prop_mu_y
  393. );
  394. return Err(Error::ProposalPublicValuesMismatched)
  395. }
  396. // rho
  397. let prop_mu_rho = lf.public_inputs[constants::PI_MU_RHO_INDEX];
  398. if mu_rho != prop_mu_rho {
  399. error!(
  400. "receive_proposal(): Failed to verify mu_rho: {:?}, proposed: {:?}",
  401. mu_rho, prop_mu_rho
  402. );
  403. return Err(Error::ProposalPublicValuesMismatched)
  404. }
  405. // Validate proposal coin sigmas against current slot checkpoint
  406. let checkpoint = self.consensus.get_slot_checkpoint(current)?;
  407. // sigma1
  408. let prop_sigma1 = lf.public_inputs[constants::PI_SIGMA1_INDEX];
  409. if checkpoint.sigma1 != prop_sigma1 {
  410. error!(
  411. "receive_proposal(): Failed to verify public value sigma1: {:?}, to proposed: {:?}",
  412. checkpoint.sigma1, prop_sigma1
  413. );
  414. }
  415. // sigma2
  416. let prop_sigma2 = lf.public_inputs[constants::PI_SIGMA2_INDEX];
  417. if checkpoint.sigma2 != prop_sigma2 {
  418. error!(
  419. "receive_proposal(): Failed to verify public value sigma2: {:?}, to proposed: {:?}",
  420. checkpoint.sigma2, prop_sigma2
  421. );
  422. }
  423. // Create corresponding state checkpoint for validations
  424. let mut state_checkpoint = match index {
  425. -1 => {
  426. // Extends canonical
  427. StateCheckpoint::new(
  428. proposal.clone(),
  429. self.consensus.coins.clone(),
  430. self.consensus.coins_tree.clone(),
  431. self.consensus.nullifiers.clone(),
  432. )
  433. }
  434. _ => {
  435. // Extends a fork
  436. let previous = self.consensus.forks[index as usize].sequence.last().unwrap();
  437. StateCheckpoint::new(
  438. proposal.clone(),
  439. previous.coins.clone(),
  440. previous.coins_tree.clone(),
  441. previous.nullifiers.clone(),
  442. )
  443. }
  444. };
  445. // Check if proposal coin nullifiers already exist in the state checkpoint
  446. let prop_sn = lf.public_inputs[constants::PI_NULLIFIER_INDEX];
  447. for sn in &state_checkpoint.nullifiers {
  448. if *sn == prop_sn {
  449. error!("receive_proposal(): Proposal nullifiers exist.");
  450. return Err(Error::ProposalIsSpent)
  451. }
  452. }
  453. /*
  454. // TODO: Validate that proposal coin is already published.
  455. let tree_root: MerkleNode = self.consensus.coins_tree.root(0).unwrap();
  456. let prop_cm_root: pallas::Base = lf.public_inputs[constants::PI_COMMITMENT_ROOT];
  457. if tree_root.inner() <= prop_cm_root {
  458. error!("validation of tree root failed");
  459. info!("tree_root: {:?}", tree_root.inner());
  460. info!("prop_root: {:?}", prop_cm_root);
  461. }
  462. */
  463. // Validate state transition against canonical state
  464. // TODO: This should be validated against fork state
  465. info!("receive_proposal(): Starting state transition validation");
  466. if let Err(e) = self.verify_transactions(&proposal.block.txs, false).await {
  467. error!("receive_proposal(): Transaction verifications failed: {}", e);
  468. return Err(e)
  469. };
  470. // TODO: [PLACEHOLDER] Add rewards validation
  471. // If proposal came fromself, we derive new coin
  472. if let Some((idx, c)) = coin {
  473. state_checkpoint.coins[idx] = c.derive_coin(&mut state_checkpoint.coins_tree);
  474. }
  475. // Store proposal coins nullifiers
  476. state_checkpoint.nullifiers.push(prop_sn);
  477. // Extend corresponding chain
  478. match index {
  479. -1 => {
  480. let fork = Fork::new(self.consensus.genesis_block, state_checkpoint);
  481. self.consensus.forks.push(fork);
  482. }
  483. _ => {
  484. self.consensus.forks[index as usize].add(&state_checkpoint);
  485. }
  486. };
  487. Ok(())
  488. }
  489. /// Remove provided transactions vector from unconfirmed_txs if they exist.
  490. pub fn remove_txs(&mut self, transactions: &Vec<Transaction>) -> Result<()> {
  491. for tx in transactions {
  492. if let Some(pos) = self.unconfirmed_txs.iter().position(|txs| txs == tx) {
  493. self.unconfirmed_txs.remove(pos);
  494. }
  495. }
  496. Ok(())
  497. }
  498. /// Node checks if any of the fork chains can be finalized.
  499. /// Consensus finalization logic:
  500. /// - If the node has observed the creation of 3 proposals in a fork chain and no other
  501. /// forks exists at same or greater height, it finalizes (appends to canonical blockchain)
  502. /// all proposals up to the last one.
  503. /// When fork chain proposals are finalized, the rest of fork chains are removed and all
  504. /// slot checkpoints until current slot are apppended to canonical state.
  505. pub async fn chain_finalization(&mut self) -> Result<(Vec<BlockInfo>, Vec<SlotCheckpoint>)> {
  506. let slot = self.consensus.current_slot();
  507. info!("chain_finalization(): Started finalization check for slot: {}", slot);
  508. // Set last slot finalization check occured to current slot
  509. self.consensus.checked_finalization = slot;
  510. // First we find longest fork without any other forks at same height
  511. let mut fork_index = -1;
  512. // Use this index to extract leaders count sequence from longest fork
  513. let mut index_for_history = -1;
  514. let mut max_length = 0;
  515. for (index, fork) in self.consensus.forks.iter().enumerate() {
  516. let length = fork.sequence.len();
  517. // Check if greater than max to retain index for history
  518. if length > max_length {
  519. index_for_history = index as i64;
  520. }
  521. // Ignore forks with less that 3 blocks
  522. if length < 3 {
  523. continue
  524. }
  525. // Check if less than max
  526. if length < max_length {
  527. continue
  528. }
  529. // Check if same length as max
  530. if length == max_length {
  531. // Setting fork_index so we know we have multiple
  532. // forks at same length.
  533. fork_index = -2;
  534. continue
  535. }
  536. // Set fork as max
  537. fork_index = index as i64;
  538. max_length = length;
  539. }
  540. // Check if we found any fork to finalize
  541. match fork_index {
  542. -2 => {
  543. info!("chain_finalization(): Eligible forks with same height exist, nothing to finalize.");
  544. self.consensus.set_leader_history(index_for_history);
  545. return Ok((vec![], vec![]))
  546. }
  547. -1 => {
  548. info!("chain_finalization(): All chains have less than 3 proposals, nothing to finalize.");
  549. self.consensus.set_leader_history(index_for_history);
  550. return Ok((vec![], vec![]))
  551. }
  552. _ => info!("chain_finalization(): Chain {} can be finalized!", fork_index),
  553. }
  554. // Starting finalization
  555. let mut fork = self.consensus.forks[fork_index as usize].clone();
  556. // Retrieving proposals to finalize
  557. let bound = max_length - 1;
  558. let mut finalized: Vec<BlockInfo> = vec![];
  559. let mut last_state_checkpoint = fork.sequence.first().unwrap().clone();
  560. for state_checkpoint in &fork.sequence[..bound] {
  561. finalized.push(state_checkpoint.proposal.clone().into());
  562. last_state_checkpoint = state_checkpoint.clone();
  563. }
  564. // Removing finalized proposals state checkpoins from fork
  565. fork.sequence.drain(..bound);
  566. // Adding finalized proposals to canonical
  567. info!("consensus: Adding {} finalized block to canonical chain.", finalized.len());
  568. match self.blockchain.add(&finalized) {
  569. Ok(v) => v,
  570. Err(e) => {
  571. error!("consensus: Failed appending finalized blocks to canonical chain: {}", e);
  572. return Err(e)
  573. }
  574. };
  575. let blocks_subscriber = self.subscribers.get("blocks").unwrap().clone();
  576. // Validating state transitions
  577. for proposal in &finalized {
  578. // TODO: Is this the right place? We're already doing this in protocol_sync.
  579. // TODO: These state transitions have already been checked. (I wrote this, but where?)
  580. // TODO: FIXME: The state transitions have already been written, they have to be in memory
  581. // until this point.
  582. info!(target: "consensus", "Applying state transition for finalized block");
  583. if let Err(e) = self.verify_transactions(&proposal.txs, true).await {
  584. error!(target: "consensus", "Finalized block transaction verifications failed: {}", e);
  585. return Err(e)
  586. }
  587. // Remove proposal transactions from memory pool
  588. if let Err(e) = self.remove_txs(&proposal.txs) {
  589. error!(target: "consensus", "Removing finalized block transactions failed: {}", e);
  590. return Err(e)
  591. }
  592. // TODO: Don't hardcode this:
  593. let params = json!([bs58::encode(&serialize(proposal)).into_string()]);
  594. let notif = JsonNotification::new("blockchain.subscribe_blocks", params);
  595. info!("consensus: Sending notification about finalized block");
  596. blocks_subscriber.notify(notif).await;
  597. }
  598. // Setting leaders history to last proposal leaders count
  599. self.consensus.leaders_history =
  600. vec![fork.sequence.last().unwrap().proposal.block.lead_info.leaders];
  601. // Removing rest forks
  602. self.consensus.forks = vec![];
  603. self.consensus.forks.push(fork);
  604. // Setting canonical states from last finalized checkpoint
  605. self.consensus.coins = last_state_checkpoint.coins;
  606. self.consensus.coins_tree = last_state_checkpoint.coins_tree;
  607. self.consensus.nullifiers = last_state_checkpoint.nullifiers;
  608. // Adding finalized slot checkpoints to canonical
  609. let mut bound = 0;
  610. let mut finalized_slot_checkpoints: Vec<SlotCheckpoint> = vec![];
  611. for (index, slot_checkpoint) in self.consensus.slot_checkpoints.iter().enumerate() {
  612. if slot_checkpoint.slot >= slot {
  613. break
  614. }
  615. bound = index;
  616. finalized_slot_checkpoints.push(slot_checkpoint.clone());
  617. }
  618. // Removing finalized proposals from chain
  619. self.consensus.slot_checkpoints.drain(..bound);
  620. debug!(
  621. "consensus: Adding {} finalized slot checkpoints to canonical chain.",
  622. finalized_slot_checkpoints.len()
  623. );
  624. match self.blockchain.add_slot_checkpoints(&finalized_slot_checkpoints) {
  625. Ok(v) => v,
  626. Err(e) => {
  627. error!(
  628. "consensus: Failed appending finalized slot checkpoints to canonical chain: {}",
  629. e
  630. );
  631. return Err(e)
  632. }
  633. };
  634. Ok((finalized, finalized_slot_checkpoints))
  635. }
  636. // ==========================
  637. // State transition functions
  638. // ==========================
  639. // TODO TESTNET: Write down all cases below
  640. // State transition checks should be happening in the following cases for a sync node:
  641. // 1) When a finalized block is received
  642. // 2) When a transaction is being broadcasted to us
  643. // State transition checks should be happening in the following cases for a consensus participating node:
  644. // 1) When a finalized block is received
  645. // 2) When a transaction is being broadcasted to us
  646. // ==========================
  647. /// Validate and append to canonical state received blocks.
  648. pub async fn receive_blocks(&mut self, blocks: &[BlockInfo]) -> Result<()> {
  649. // Verify state transitions for all blocks and their respective transactions.
  650. info!("receive_blocks(): Starting state transition validations");
  651. for block in blocks {
  652. if let Err(e) = self.verify_transactions(&block.txs, false).await {
  653. error!("receive_blocks(): Transaction verifications failed: {}", e);
  654. return Err(e)
  655. }
  656. }
  657. info!("receive_blocks(): All state transitions passed");
  658. info!("receive_blocks(): Appending blocks to ledger");
  659. self.blockchain.add(blocks)?;
  660. Ok(())
  661. }
  662. /// Validate and append to canonical state received finalized block.
  663. /// Returns boolean flag indicating already existing block.
  664. pub async fn receive_finalized_block(&mut self, block: BlockInfo) -> Result<bool> {
  665. match self.blockchain.has_block(&block) {
  666. Ok(v) => {
  667. if v {
  668. info!("receive_finalized_block(): Existing block received");
  669. return Ok(false)
  670. }
  671. }
  672. Err(e) => {
  673. error!("receive_finalized_block(): failed checking for has_block(): {}", e);
  674. return Ok(false)
  675. }
  676. };
  677. info!("receive_finalized_block(): Executing state transitions");
  678. self.receive_blocks(&[block.clone()]).await?;
  679. // TODO: Don't hardcode this:
  680. let blocks_subscriber = self.subscribers.get("blocks").unwrap();
  681. let params = json!([bs58::encode(&serialize(&block)).into_string()]);
  682. let notif = JsonNotification::new("blockchain.subscribe_blocks", params);
  683. info!("consensus: Sending notification about finalized block");
  684. blocks_subscriber.notify(notif).await;
  685. info!("receive_finalized_block(): Removing block transactions from unconfirmed_txs");
  686. self.remove_txs(&block.txs)?;
  687. Ok(true)
  688. }
  689. /// Validate and append to canonical state received finalized blocks from block sync task.
  690. /// Already existing blocks are ignored.
  691. pub async fn receive_sync_blocks(&mut self, blocks: &[BlockInfo]) -> Result<()> {
  692. let mut new_blocks = vec![];
  693. for block in blocks {
  694. match self.blockchain.has_block(block) {
  695. Ok(v) => {
  696. if v {
  697. info!("receive_sync_blocks(): Existing block received");
  698. continue
  699. }
  700. new_blocks.push(block.clone());
  701. }
  702. Err(e) => {
  703. error!("receive_sync_blocks(): failed checking for has_block(): {}", e);
  704. continue
  705. }
  706. };
  707. }
  708. if new_blocks.is_empty() {
  709. info!("receive_sync_blocks(): no new blocks to append");
  710. return Ok(())
  711. }
  712. info!("receive_sync_blocks(): Executing state transitions");
  713. self.receive_blocks(&new_blocks[..]).await?;
  714. // TODO: Don't hardcode this:
  715. let blocks_subscriber = self.subscribers.get("blocks").unwrap();
  716. for block in new_blocks {
  717. let params = json!([bs58::encode(&serialize(&block)).into_string()]);
  718. let notif = JsonNotification::new("blockchain.subscribe_blocks", params);
  719. info!("consensus: Sending notification about finalized block");
  720. blocks_subscriber.notify(notif).await;
  721. }
  722. Ok(())
  723. }
  724. /// Validate signatures, wasm execution, and zk proofs for given transactions.
  725. /// If all of those succeed, try to execute a state update for the contract calls.
  726. /// Currently the verifications are sequential, and the function will fail if any
  727. /// of the verifications fail.
  728. /// The function takes a boolean called `write` which tells it to actually write
  729. /// the state transitions to the database.
  730. // TODO: This should be paralellized as if even one tx in the batch fails to verify,
  731. // we can drop everything.
  732. pub async fn verify_transactions(&self, txs: &[Transaction], write: bool) -> Result<()> {
  733. info!("Verifying {} transaction(s)", txs.len());
  734. for tx in txs {
  735. let tx_hash = blake3::hash(&serialize(tx));
  736. info!("Verifying transaction {}", tx_hash);
  737. // Table of public inputs used for ZK proof verification
  738. let mut zkp_table = vec![];
  739. // Table of public keys used for signature verification
  740. let mut sig_table = vec![];
  741. // State updates produced by contract execcution
  742. let mut updates = vec![];
  743. // Iterate over all calls to get the metadata
  744. for (idx, call) in tx.calls.iter().enumerate() {
  745. info!("Executing contract call {}", idx);
  746. let wasm = match self.blockchain.wasm_bincode.get(call.contract_id) {
  747. Ok(v) => {
  748. info!("Found wasm bincode for {}", call.contract_id);
  749. v
  750. }
  751. Err(e) => {
  752. error!(
  753. "Could not find wasm bincode for contract {}: {}",
  754. call.contract_id, e
  755. );
  756. return Err(Error::ContractNotFound(call.contract_id.to_string()))
  757. }
  758. };
  759. // Write the actual payload data
  760. let mut payload = vec![];
  761. payload.write_u32(idx as u32)?; // Call index
  762. tx.calls.encode(&mut payload)?; // Actual call data
  763. // Instantiate the wasm runtime
  764. let mut runtime =
  765. match Runtime::new(&wasm, self.blockchain.clone(), call.contract_id) {
  766. Ok(v) => v,
  767. Err(e) => {
  768. error!(
  769. "Failed to instantiate WASM runtime for contract {}",
  770. call.contract_id
  771. );
  772. return Err(e)
  773. }
  774. };
  775. info!("Executing \"metadata\" call");
  776. let metadata = match runtime.metadata(&payload) {
  777. Ok(v) => v,
  778. Err(e) => {
  779. error!("Failed to execute \"metadata\" call: {}", e);
  780. return Err(e)
  781. }
  782. };
  783. // Decode the metadata retrieved from the execution
  784. let mut decoder = Cursor::new(&metadata);
  785. let zkp_pub: Vec<(String, Vec<pallas::Base>)> =
  786. match Decodable::decode(&mut decoder) {
  787. Ok(v) => v,
  788. Err(e) => {
  789. error!("Failed to decode ZK public inputs from metadata: {}", e);
  790. return Err(e.into())
  791. }
  792. };
  793. let sig_pub: Vec<PublicKey> = match Decodable::decode(&mut decoder) {
  794. Ok(v) => v,
  795. Err(e) => {
  796. error!("Failed to decode signature pubkeys from metadata: {}", e);
  797. return Err(e.into())
  798. }
  799. };
  800. // TODO: Make sure we've read all the bytes above.
  801. info!("Successfully executed \"metadata\" call");
  802. zkp_table.push(zkp_pub);
  803. sig_table.push(sig_pub);
  804. // After getting the metadata, we run the "exec" function with the same
  805. // runtime and the same payload.
  806. info!("Executing \"exec\" call");
  807. match runtime.exec(&payload) {
  808. Ok(v) => {
  809. info!("Successfully executed \"exec\" call");
  810. updates.push(v);
  811. }
  812. Err(e) => {
  813. error!(
  814. "Failed to execute \"exec\" call for contract id {}: {}",
  815. call.contract_id, e
  816. );
  817. return Err(e)
  818. }
  819. };
  820. // At this point we're done with the call and move on to the next one.
  821. }
  822. // When we're done looping and executing over the tx's contract calls, we
  823. // move on with verification. First we verify the signatures as that's
  824. // cheaper, and then finally we verify the ZK proofs.
  825. info!("Verifying signatures for transaction {}", tx_hash);
  826. if sig_table.len() != tx.signatures.len() {
  827. error!("Incorrect number of signatures in tx {}", tx_hash);
  828. return Err(Error::InvalidSignature)
  829. }
  830. match tx.verify_sigs(sig_table) {
  831. Ok(()) => info!("Signatures verification for tx {} successful", tx_hash),
  832. Err(e) => {
  833. error!("Signature verification for tx {} failed: {}", tx_hash, e);
  834. return Err(e)
  835. }
  836. };
  837. // NOTE: When it comes to the ZK proofs, we first do a lookup of the
  838. // verifying keys, but if we do not find them, we'll generate them
  839. // inside of this function. This can be kinda expensive, so open to
  840. // alternatives.
  841. info!("Verifying ZK proofs for transaction {}", tx_hash);
  842. match tx.verify_zkps(self.verifying_keys.clone(), zkp_table).await {
  843. Ok(()) => info!("ZK proof verification for tx {} successful", tx_hash),
  844. Err(e) => {
  845. error!("ZK proof verification for tx {} failed: {}", tx_hash, e);
  846. return Err(e)
  847. }
  848. };
  849. // After the verifications stage passes, if we're told to write, we
  850. // apply the state updates.
  851. assert!(tx.calls.len() == updates.len());
  852. if write {
  853. info!("Performing state updates");
  854. for (call, update) in tx.calls.iter().zip(updates.iter()) {
  855. // For this we instantiate the runtimes again.
  856. // TODO: Optimize this
  857. // TODO: Sum up the gas costs of previous calls during execution
  858. // and verification and these.
  859. let wasm = match self.blockchain.wasm_bincode.get(call.contract_id) {
  860. Ok(v) => {
  861. info!("Found wasm bincode for {}", call.contract_id);
  862. v
  863. }
  864. Err(e) => {
  865. error!(
  866. "Could not find wasm bincode for contract {}: {}",
  867. call.contract_id, e
  868. );
  869. return Err(Error::ContractNotFound(call.contract_id.to_string()))
  870. }
  871. };
  872. let mut runtime =
  873. match Runtime::new(&wasm, self.blockchain.clone(), call.contract_id) {
  874. Ok(v) => v,
  875. Err(e) => {
  876. error!(
  877. "Failed to instantiate WASM runtime for contract {}",
  878. call.contract_id
  879. );
  880. return Err(e)
  881. }
  882. };
  883. info!("Executing \"apply\" call");
  884. match runtime.apply(update) {
  885. // TODO: FIXME: This should be done in an atomic tx/batch
  886. Ok(()) => info!("State update applied successfully"),
  887. Err(e) => {
  888. error!("Failed to apply state update: {}", e);
  889. return Err(e)
  890. }
  891. };
  892. }
  893. } else {
  894. info!("Skipping apply of state updates because write=false");
  895. }
  896. info!("Transaction {} verified successfully", tx_hash);
  897. }
  898. Ok(())
  899. }
  900. /// Append to canonical state received finalized slot checkpoints from block sync task.
  901. pub async fn receive_slot_checkpoints(
  902. &mut self,
  903. slot_checkpoints: &[SlotCheckpoint],
  904. ) -> Result<()> {
  905. info!("receive_slot_checkpoints(): Appending slot checkpoints to ledger");
  906. self.blockchain.add_slot_checkpoints(slot_checkpoints)?;
  907. Ok(())
  908. }
  909. /// Validate and append to canonical state received finalized slot checkpoint.
  910. /// Returns boolean flag indicating already existing slot checkpoint.
  911. pub async fn receive_finalized_slot_checkpoints(
  912. &mut self,
  913. slot_checkpoint: SlotCheckpoint,
  914. ) -> Result<bool> {
  915. match self.blockchain.has_slot_checkpoint(&slot_checkpoint) {
  916. Ok(v) => {
  917. if v {
  918. info!(
  919. "receive_finalized_slot_checkpoints(): Existing slot checkpoint received"
  920. );
  921. return Ok(false)
  922. }
  923. }
  924. Err(e) => {
  925. error!("receive_finalized_slot_checkpoints(): failed checking for has_slot_checkpoint(): {}", e);
  926. return Ok(false)
  927. }
  928. };
  929. self.receive_slot_checkpoints(&[slot_checkpoint]).await?;
  930. Ok(true)
  931. }
  932. }