state.rs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882
  1. // TODO: Use sets instead of vectors where possible.
  2. use std::{
  3. collections::{hash_map::DefaultHasher, BTreeMap},
  4. hash::{Hash, Hasher},
  5. time::Duration,
  6. };
  7. use async_std::sync::{Arc, Mutex, RwLock};
  8. use chrono::{NaiveDateTime, Utc};
  9. use lazy_init::Lazy;
  10. use log::{debug, error, info, warn};
  11. use rand::rngs::OsRng;
  12. use super::{
  13. Block, BlockInfo, BlockProposal, Metadata, Participant, ProposalChain, StreamletMetadata,
  14. Timestamp, Tx, Vote,
  15. };
  16. use crate::{
  17. blockchain::Blockchain,
  18. crypto::{
  19. address::Address,
  20. keypair::{PublicKey, SecretKey},
  21. schnorr::{SchnorrPublic, SchnorrSecret},
  22. },
  23. net,
  24. node::{
  25. state::{state_transition, StateUpdate},
  26. Client, MemoryState, State,
  27. },
  28. util::serial::{serialize, Encodable, SerialDecodable, SerialEncodable},
  29. Result,
  30. };
  31. /// `2 * DELTA` represents epoch time
  32. pub const DELTA: u64 = 30;
  33. /// This struct represents the information required by the consensus algorithm
  34. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  35. pub struct ConsensusState {
  36. /// Genesis block creation timestamp
  37. pub genesis_ts: Timestamp,
  38. /// Genesis block hash
  39. pub genesis_block: blake3::Hash,
  40. /// Fork chains containing block proposals
  41. pub proposals: Vec<ProposalChain>,
  42. /// Orphan votes pool, in case a vote reaches a node before the
  43. /// corresponding block
  44. pub orphan_votes: Vec<Vote>,
  45. /// Validators currently participating in the consensus
  46. pub participants: BTreeMap<Address, Participant>,
  47. /// Validators to be added on the next epoch as participants
  48. pub pending_participants: Vec<Participant>,
  49. /// Last slot participants where refreshed
  50. pub refreshed: u64,
  51. }
  52. impl ConsensusState {
  53. pub fn new(genesis_ts: Timestamp, genesis_data: blake3::Hash) -> Result<Self> {
  54. let genesis_block =
  55. blake3::hash(&serialize(&Block::genesis_block(genesis_ts, genesis_data)));
  56. Ok(Self {
  57. genesis_ts,
  58. genesis_block,
  59. proposals: vec![],
  60. orphan_votes: vec![],
  61. participants: BTreeMap::new(),
  62. pending_participants: vec![],
  63. refreshed: 0,
  64. })
  65. }
  66. }
  67. /// Auxiliary structure used for consensus syncing.
  68. #[derive(Debug, SerialEncodable, SerialDecodable)]
  69. pub struct ConsensusRequest {
  70. /// Validator wallet address
  71. pub address: Address,
  72. }
  73. impl net::Message for ConsensusRequest {
  74. fn name() -> &'static str {
  75. "consensusrequest"
  76. }
  77. }
  78. /// Auxiliary structure used for consensus syncing.
  79. #[derive(Debug, Clone, SerialEncodable, SerialDecodable)]
  80. pub struct ConsensusResponse {
  81. /// Hot/live data used by the consensus algorithm
  82. pub consensus: ConsensusState,
  83. }
  84. impl net::Message for ConsensusResponse {
  85. fn name() -> &'static str {
  86. "consensusresponse"
  87. }
  88. }
  89. /// Atomic pointer to validator state.
  90. pub type ValidatorStatePtr = Arc<RwLock<ValidatorState>>;
  91. /// This struct represents the state of a validator node.
  92. pub struct ValidatorState {
  93. /// Node wallet address
  94. pub address: Address,
  95. /// Secret key, to sign messages
  96. pub secret: SecretKey,
  97. /// Node public key
  98. pub public: PublicKey,
  99. /// Hot/Live data used by the consensus algorithm
  100. pub consensus: ConsensusState,
  101. /// Canonical (finalized) blockchain
  102. pub blockchain: Blockchain,
  103. /// Canonical state machine
  104. pub state_machine: Arc<Mutex<State>>,
  105. /// Client providing wallet access
  106. pub client: Arc<Client>,
  107. /// Pending transactions
  108. pub unconfirmed_txs: Vec<Tx>,
  109. /// Participating start epoch
  110. pub participating: Option<u64>,
  111. }
  112. impl ValidatorState {
  113. // TODO: Clock sync
  114. pub async fn new(
  115. db: &sled::Db, // <-- TODO: Avoid this with some wrapping, sled should only be in blockchain
  116. genesis_ts: Timestamp,
  117. genesis_data: blake3::Hash,
  118. client: Arc<Client>,
  119. cashier_pubkeys: Vec<PublicKey>,
  120. faucet_pubkeys: Vec<PublicKey>,
  121. ) -> Result<ValidatorStatePtr> {
  122. let secret = SecretKey::random(&mut OsRng);
  123. let public = PublicKey::from_secret(secret);
  124. let consensus = ConsensusState::new(genesis_ts, genesis_data)?;
  125. let blockchain = Blockchain::new(db, genesis_ts, genesis_data)?;
  126. let unconfirmed_txs = vec![];
  127. let participating = None;
  128. let address = client.wallet.get_default_address().await?;
  129. let state_machine = Arc::new(Mutex::new(State {
  130. tree: client.get_tree().await?,
  131. merkle_roots: blockchain.merkle_roots.clone(),
  132. nullifiers: blockchain.nullifiers.clone(),
  133. cashier_pubkeys,
  134. faucet_pubkeys,
  135. mint_vk: Lazy::new(),
  136. burn_vk: Lazy::new(),
  137. }));
  138. let state = Arc::new(RwLock::new(ValidatorState {
  139. address,
  140. secret,
  141. public,
  142. consensus,
  143. blockchain,
  144. state_machine,
  145. client,
  146. unconfirmed_txs,
  147. participating,
  148. }));
  149. Ok(state)
  150. }
  151. /// The node retrieves a transaction and appends it to the unconfirmed
  152. /// transactions list. Additional validity rules must be defined by the
  153. /// protocol for transactions.
  154. pub fn append_tx(&mut self, tx: Tx) -> bool {
  155. if self.unconfirmed_txs.contains(&tx) {
  156. debug!("append_tx(): We already have this tx");
  157. return false
  158. }
  159. debug!("append_tx(): Appended tx to mempool");
  160. self.unconfirmed_txs.push(tx);
  161. true
  162. }
  163. /// Calculates current epoch, based on elapsed time from the genesis block.
  164. /// Epoch duration is configured using the `DELTA` value.
  165. pub fn current_epoch(&self) -> u64 {
  166. self.consensus.genesis_ts.elapsed() / (2 * DELTA)
  167. }
  168. /// Finds the last epoch a proposal or block was generated.
  169. pub fn last_epoch(&self) -> Result<u64> {
  170. let mut epoch = 0;
  171. for chain in &self.consensus.proposals {
  172. for proposal in &chain.proposals {
  173. if proposal.block.sl > epoch {
  174. epoch = proposal.block.sl;
  175. }
  176. }
  177. }
  178. // We return here in case proposals exist,
  179. // so we don't query the sled database.
  180. if epoch > 0 {
  181. return Ok(epoch)
  182. }
  183. let (last_sl, _) = self.blockchain.last()?.unwrap();
  184. Ok(last_sl)
  185. }
  186. /// Calculates seconds until next epoch starting time.
  187. /// Epochs durationis configured using the delta value.
  188. pub fn next_epoch_start(&self) -> Duration {
  189. let start_time = NaiveDateTime::from_timestamp(self.consensus.genesis_ts.0, 0);
  190. let current_epoch = self.current_epoch() + 1;
  191. let next_epoch_start = (current_epoch * (2 * DELTA)) + (start_time.timestamp() as u64);
  192. let next_epoch_start = NaiveDateTime::from_timestamp(next_epoch_start as i64, 0);
  193. let current_time = NaiveDateTime::from_timestamp(Utc::now().timestamp(), 0);
  194. let diff = next_epoch_start - current_time;
  195. Duration::new(diff.num_seconds().try_into().unwrap(), 0)
  196. }
  197. /// Set participating epoch to next.
  198. pub fn set_participating(&mut self) -> Result<()> {
  199. self.participating = Some(self.current_epoch() + 1);
  200. Ok(())
  201. }
  202. /// Find epoch leader, using a simple hash method.
  203. /// Leader calculation is based on how many nodes are participating
  204. /// in the network.
  205. pub fn epoch_leader(&mut self) -> Address {
  206. let epoch = self.current_epoch();
  207. // DefaultHasher is used to hash the epoch number
  208. // because it produces a number string which then can be modulated by the len.
  209. // blake3 produces alphanumeric
  210. let mut hasher = DefaultHasher::new();
  211. epoch.hash(&mut hasher);
  212. let pos = hasher.finish() % (self.consensus.participants.len() as u64);
  213. // Since BTreeMap orders by key in asceding order, each node will have
  214. // the same key in calculated position.
  215. self.consensus.participants.iter().nth(pos as usize).unwrap().1.address
  216. }
  217. /// Check if we're the current epoch leader
  218. pub fn is_epoch_leader(&mut self) -> bool {
  219. let address = self.address;
  220. address == self.epoch_leader()
  221. }
  222. /// Generate a block proposal for the current epoch, containing all
  223. /// unconfirmed transactions. Proposal extends the longest notarized fork
  224. /// chain the node is holding.
  225. pub fn propose(&self) -> Result<Option<BlockProposal>> {
  226. let epoch = self.current_epoch();
  227. let (prev_hash, index) = self.longest_notarized_chain_last_hash().unwrap();
  228. let unproposed_txs = self.unproposed_txs(index);
  229. let metadata = Metadata::new(
  230. Timestamp::current_time(),
  231. String::from("proof"),
  232. String::from("r"),
  233. String::from("s"),
  234. );
  235. let sm = StreamletMetadata::new(self.consensus.participants.values().cloned().collect());
  236. let prop = BlockProposal::to_proposal_hash(prev_hash, epoch, &unproposed_txs, &metadata);
  237. let signed_proposal = self.secret.sign(&prop.as_bytes()[..]);
  238. Ok(Some(BlockProposal::new(
  239. self.public,
  240. signed_proposal,
  241. self.address,
  242. prev_hash,
  243. epoch,
  244. unproposed_txs,
  245. metadata,
  246. sm,
  247. )))
  248. }
  249. /// Retrieve all unconfirmed transactions not proposed in previous blocks
  250. /// of provided index chain.
  251. pub fn unproposed_txs(&self, index: i64) -> Vec<Tx> {
  252. let mut unproposed_txs = self.unconfirmed_txs.clone();
  253. // If index is -1 (canonical blockchain) a new fork will be generated,
  254. // therefore all unproposed transactions can be included in the proposal.
  255. if index == -1 {
  256. return unproposed_txs
  257. }
  258. // We iterate over the fork chain proposals to find already proposed
  259. // transactions and remove them from the local unproposed_txs vector.
  260. let chain = &self.consensus.proposals[index as usize];
  261. for proposal in &chain.proposals {
  262. for tx in &proposal.block.txs {
  263. if let Some(pos) = unproposed_txs.iter().position(|txs| *txs == *tx) {
  264. unproposed_txs.remove(pos);
  265. }
  266. }
  267. }
  268. unproposed_txs
  269. }
  270. /// Finds the longest fully notarized blockchain the node holds and
  271. /// returns the last block hash and the chain index.
  272. pub fn longest_notarized_chain_last_hash(&self) -> Result<(blake3::Hash, i64)> {
  273. let mut longest_notarized_chain: Option<ProposalChain> = None;
  274. let mut length = 0;
  275. let mut index = -1;
  276. if !self.consensus.proposals.is_empty() {
  277. for (i, chain) in self.consensus.proposals.iter().enumerate() {
  278. if chain.notarized() && chain.proposals.len() > length {
  279. longest_notarized_chain = Some(chain.clone());
  280. length = chain.proposals.len();
  281. index = i as i64;
  282. }
  283. }
  284. }
  285. let hash = match longest_notarized_chain {
  286. Some(chain) => chain.proposals.last().unwrap().hash(),
  287. None => self.blockchain.last()?.unwrap().1,
  288. };
  289. Ok((hash, index))
  290. }
  291. /// Receive the proposed block, verify its sender (epoch leader),
  292. /// and proceed with voting on it.
  293. pub fn receive_proposal(&mut self, proposal: &BlockProposal) -> Result<Option<Vote>> {
  294. // Node hasn't started participating
  295. match self.participating {
  296. Some(start) => {
  297. if self.current_epoch() < start {
  298. return Ok(None)
  299. }
  300. }
  301. None => return Ok(None),
  302. }
  303. // Node refreshes participants records
  304. self.refresh_participants()?;
  305. let leader = self.epoch_leader();
  306. if leader != proposal.address {
  307. warn!(
  308. "Received proposal not from epoch leader ({}), but from ({})",
  309. leader,
  310. proposal.address.to_string()
  311. );
  312. return Ok(None)
  313. }
  314. if !proposal.public_key.verify(
  315. BlockProposal::to_proposal_hash(
  316. proposal.block.st,
  317. proposal.block.sl,
  318. &proposal.block.txs,
  319. &proposal.block.metadata,
  320. )
  321. .as_bytes(),
  322. &proposal.signature,
  323. ) {
  324. warn!("Proposer ({}) signature could not be verified", proposal.address.to_string());
  325. return Ok(None)
  326. }
  327. self.vote(proposal)
  328. }
  329. /// Given a proposal, the node finds which blockchain it extends.
  330. /// If the proposal extends the canonical blockchain, a new fork chain
  331. /// is created. The node votes on the proposal only if it extends the
  332. /// longest notarized fork chain it has seen.
  333. pub fn vote(&mut self, proposal: &BlockProposal) -> Result<Option<Vote>> {
  334. let mut proposal = proposal.clone();
  335. // Generate proposal hash
  336. let proposal_hash = proposal.hash();
  337. // Add orphan votes
  338. let mut orphans = Vec::new();
  339. for vote in self.consensus.orphan_votes.iter() {
  340. if vote.proposal == proposal_hash {
  341. proposal.block.sm.votes.push(vote.clone());
  342. orphans.push(vote.clone());
  343. }
  344. }
  345. for vote in orphans {
  346. self.consensus.orphan_votes.retain(|v| *v != vote);
  347. }
  348. let index = self.find_extended_chain_index(&proposal)?;
  349. if index == -2 {
  350. return Ok(None)
  351. }
  352. let chain = match index {
  353. -1 => {
  354. let pc = ProposalChain::new(self.consensus.genesis_block, proposal.clone());
  355. self.consensus.proposals.push(pc);
  356. self.consensus.proposals.last().unwrap()
  357. }
  358. _ => {
  359. self.consensus.proposals[index as usize].add(&proposal);
  360. &self.consensus.proposals[index as usize]
  361. }
  362. };
  363. if !self.extends_notarized_chain(chain) {
  364. debug!("vote(): Proposal does not extend notarized chain");
  365. return Ok(None)
  366. }
  367. let signed_hash = self.secret.sign(&serialize(&proposal_hash));
  368. Ok(Some(Vote::new(
  369. self.public,
  370. signed_hash,
  371. proposal_hash,
  372. proposal.block.sl,
  373. self.address,
  374. )))
  375. }
  376. /// Verify if the provided chain is notarized excluding the last block.
  377. pub fn extends_notarized_chain(&self, chain: &ProposalChain) -> bool {
  378. for proposal in &chain.proposals[..(chain.proposals.len() - 1)] {
  379. if !proposal.block.sm.notarized {
  380. return false
  381. }
  382. }
  383. true
  384. }
  385. /// Given a proposal, find the index of the chain it extends.
  386. pub fn find_extended_chain_index(&mut self, proposal: &BlockProposal) -> Result<i64> {
  387. let mut fork = None;
  388. for (index, chain) in self.consensus.proposals.iter().enumerate() {
  389. let last = chain.proposals.last().unwrap();
  390. let hash = last.hash();
  391. if proposal.block.st == hash && proposal.block.sl > last.block.sl {
  392. return Ok(index as i64)
  393. }
  394. if proposal.block.st == last.block.st && proposal.block.sl == last.block.sl {
  395. debug!("find_extended_chain_index(): Proposal already received");
  396. return Ok(-2)
  397. }
  398. if proposal.block.st == last.block.st && proposal.block.sl > last.block.sl {
  399. fork = Some(chain.clone());
  400. }
  401. }
  402. match fork {
  403. Some(mut chain) => {
  404. debug!("Proposal to fork a forkchain was received.");
  405. chain.proposals.pop(); // removing last block to create the fork
  406. if !chain.proposals.is_empty() {
  407. // if len is 0 we will verify against blockchain last block
  408. self.consensus.proposals.push(chain);
  409. return Ok(self.consensus.proposals.len() as i64 - 1)
  410. }
  411. }
  412. None => (),
  413. }
  414. let (last_sl, last_block) = self.blockchain.last()?.unwrap();
  415. if proposal.block.st != last_block || proposal.block.sl <= last_sl {
  416. debug!("find_extended_chain_index(): Proposal doesn't extend any known chain");
  417. return Ok(-2)
  418. }
  419. Ok(-1)
  420. }
  421. /// Receive a vote for a proposal.
  422. /// First, sender is verified using their public key.
  423. /// The proposal is then searched for in the node's fork chains.
  424. /// If the vote wasn't received before, it is appended to the proposal
  425. /// votes list.
  426. /// When a node sees 2n/3 votes for a proposal, it notarizes it.
  427. /// When a proposal gets notarized, the transactions it contains are
  428. /// removed from the node's unconfirmed tx list.
  429. /// Finally, we check if the notarization of the proposal can finalize
  430. /// parent proposals in its chain.
  431. pub fn receive_vote(&mut self, vote: &Vote) -> Result<(bool, Option<Vec<BlockInfo>>)> {
  432. let current_epoch = self.current_epoch();
  433. // Node hasn't started participating
  434. match self.participating {
  435. Some(start) => {
  436. if current_epoch < start {
  437. return Ok((false, None))
  438. }
  439. }
  440. None => return Ok((false, None)),
  441. }
  442. let mut encoded_proposal = vec![];
  443. match vote.proposal.encode(&mut encoded_proposal) {
  444. Ok(_) => (),
  445. Err(e) => {
  446. error!(target: "consensus", "Proposal encoding failed: {:?}", e);
  447. return Ok((false, None))
  448. }
  449. };
  450. if !vote.public_key.verify(&encoded_proposal, &vote.vote) {
  451. warn!(target: "consensus", "Voter ({}), signature couldn't be verified", vote.address.to_string());
  452. return Ok((false, None))
  453. }
  454. // Node refreshes participants records
  455. self.refresh_participants()?;
  456. let node_count = self.consensus.participants.len();
  457. // Checking that the voter can actually vote.
  458. match self.consensus.participants.get(&vote.address) {
  459. Some(participant) => {
  460. let mut participant = participant.clone();
  461. if current_epoch <= participant.joined {
  462. warn!(target: "consensus", "Voter ({}) joined after current epoch.", vote.address.to_string());
  463. return Ok((false, None))
  464. }
  465. // Updating participant vote
  466. match participant.voted {
  467. Some(voted) => {
  468. if vote.sl > voted {
  469. participant.voted = Some(vote.sl);
  470. }
  471. }
  472. None => participant.voted = Some(vote.sl),
  473. }
  474. self.consensus.participants.insert(participant.address, participant);
  475. }
  476. None => {
  477. warn!(target: "consensus", "Voter ({}) is not a participant!", vote.address.to_string());
  478. return Ok((false, None))
  479. }
  480. }
  481. let proposal = match self.find_proposal(&vote.proposal) {
  482. Ok(v) => v,
  483. Err(e) => {
  484. error!(target: "consensus", "find_proposal() failed: {}", e);
  485. return Err(e)
  486. }
  487. };
  488. if proposal.is_none() {
  489. debug!(target: "consensus", "Received vote for unknown proposal.");
  490. if !self.consensus.orphan_votes.contains(vote) {
  491. self.consensus.orphan_votes.push(vote.clone());
  492. }
  493. return Ok((false, None))
  494. }
  495. let (proposal, chain_idx) = proposal.unwrap();
  496. if proposal.block.sm.votes.contains(vote) {
  497. debug!("receive_vote(): Already seen this vote");
  498. return Ok((false, None))
  499. }
  500. proposal.block.sm.votes.push(vote.clone());
  501. let mut to_broadcast = vec![];
  502. if !proposal.block.sm.notarized && proposal.block.sm.votes.len() > (2 * node_count / 3) {
  503. debug!("receive_vote(): Notarized a block");
  504. proposal.block.sm.notarized = true;
  505. match self.chain_finalization(chain_idx) {
  506. Ok(v) => {
  507. to_broadcast = v;
  508. }
  509. Err(e) => {
  510. error!(target: "consensus", "Block finalization failed: {}", e);
  511. return Err(e)
  512. }
  513. }
  514. }
  515. Ok((true, Some(to_broadcast)))
  516. }
  517. /// Search the chains we're holding for the given proposal.
  518. pub fn find_proposal(
  519. &mut self,
  520. vote_proposal: &blake3::Hash,
  521. ) -> Result<Option<(&mut BlockProposal, i64)>> {
  522. for (index, chain) in &mut self.consensus.proposals.iter_mut().enumerate() {
  523. for proposal in chain.proposals.iter_mut().rev() {
  524. let proposal_hash = proposal.hash();
  525. if vote_proposal == &proposal_hash {
  526. return Ok(Some((proposal, index as i64)))
  527. }
  528. }
  529. }
  530. Ok(None)
  531. }
  532. /// Remove provided transactions vector from unconfirmed_txs if they exist.
  533. pub fn remove_txs(&mut self, transactions: Vec<Tx>) -> Result<()> {
  534. for tx in transactions {
  535. if let Some(pos) = self.unconfirmed_txs.iter().position(|txs| *txs == tx) {
  536. self.unconfirmed_txs.remove(pos);
  537. }
  538. }
  539. Ok(())
  540. }
  541. /// Provided an index, the node checks if the chain can be finalized.
  542. /// Consensus finalization logic:
  543. /// - If the node has observed the notarization of 3 consecutive
  544. /// proposals in a fork chain, it finalizes (appends to canonical
  545. /// blockchain) all proposals up to the middle block.
  546. /// When fork chain proposals are finalized, the rest of fork chains not
  547. /// starting by those proposals are removed.
  548. pub fn chain_finalization(&mut self, chain_index: i64) -> Result<Vec<BlockInfo>> {
  549. let chain = &mut self.consensus.proposals[chain_index as usize];
  550. if chain.proposals.len() < 3 {
  551. debug!(
  552. "chain_finalization(): Less than 3 proposals in chain {}, nothing to finalize",
  553. chain_index
  554. );
  555. return Ok(vec![])
  556. }
  557. let mut consecutive = 0;
  558. for proposal in &chain.proposals {
  559. if proposal.block.sm.notarized {
  560. consecutive += 1;
  561. continue
  562. }
  563. break
  564. }
  565. if consecutive < 3 {
  566. debug!(
  567. "chain_finalization(): Less than 3 notarized blocks in chain {}, nothing to finalize",
  568. chain_index
  569. );
  570. return Ok(vec![])
  571. }
  572. let mut finalized = vec![];
  573. for proposal in &mut chain.proposals[..(consecutive - 1)] {
  574. proposal.block.sm.finalized = true;
  575. finalized.push(proposal.clone().into());
  576. }
  577. chain.proposals.drain(0..(consecutive - 1));
  578. info!(target: "consensus", "Adding finalized block to canonical chain");
  579. let blockhashes = match self.blockchain.add(&finalized) {
  580. Ok(v) => v,
  581. Err(e) => {
  582. error!(target: "consensus", "Failed appending finalized blocks to canonical chain: {}", e);
  583. return Err(e)
  584. }
  585. };
  586. for proposal in &finalized {
  587. self.remove_txs(proposal.txs.clone())?;
  588. }
  589. let last_block = *blockhashes.last().unwrap();
  590. let last_sl = finalized.last().unwrap().sl;
  591. let mut dropped = vec![];
  592. for chain in self.consensus.proposals.iter() {
  593. let first = chain.proposals.first().unwrap();
  594. if first.block.st != last_block || first.block.sl <= last_sl {
  595. dropped.push(chain.clone());
  596. }
  597. }
  598. for chain in dropped {
  599. self.consensus.proposals.retain(|c| *c != chain);
  600. }
  601. // Remove orphan votes
  602. let mut orphans = vec![];
  603. for vote in self.consensus.orphan_votes.iter() {
  604. if vote.sl <= last_sl {
  605. orphans.push(vote.clone());
  606. }
  607. }
  608. for vote in orphans {
  609. self.consensus.orphan_votes.retain(|v| *v != vote);
  610. }
  611. Ok(finalized)
  612. }
  613. /// Append a new participant to the pending participants list.
  614. pub fn append_participant(&mut self, participant: Participant) -> bool {
  615. if self.consensus.pending_participants.contains(&participant) {
  616. return false
  617. }
  618. self.consensus.pending_participants.push(participant);
  619. true
  620. }
  621. /// Refresh the participants map, to retain only the active ones.
  622. /// Active nodes are considered those that joined previous epoch
  623. /// or on the epoch the last proposal was generated, either voted
  624. /// or joined the previous of that epoch. That ensures we cover
  625. /// the case of a node joining while the chosen epoch leader is inactive.
  626. pub fn refresh_participants(&mut self) -> Result<()> {
  627. // Node checks if it should refresh its participants list
  628. let epoch = self.current_epoch();
  629. if epoch <= self.consensus.refreshed {
  630. debug!("refresh_participants(): Participants have been refreshed this epoch.");
  631. return Ok(())
  632. }
  633. debug!("refresh_participants(): Adding pending participants");
  634. for participant in &self.consensus.pending_participants {
  635. self.consensus.participants.insert(participant.address, participant.clone());
  636. }
  637. if self.consensus.pending_participants.is_empty() {
  638. debug!(
  639. "refresh_participants(): Didn't manage to add any participant, pending were empty."
  640. );
  641. }
  642. self.consensus.pending_participants = vec![];
  643. let mut inactive = Vec::new();
  644. let mut last_epoch = self.last_epoch()?;
  645. // This check ensures that we don't chech the current epoch,
  646. // as a node might receive the proposal of current epoch before
  647. // starting refreshing participants, so the last_epoch will be
  648. // the current one.
  649. if last_epoch >= epoch {
  650. last_epoch = epoch - 1;
  651. }
  652. let previous_epoch = epoch - 1;
  653. let previous_from_last_epoch = last_epoch - 1;
  654. debug!(
  655. "refresh_participants(): Node {:?} checking epochs: previous - {:?}, last - {:?}, previous from last - {:?}",
  656. self.address.to_string(), previous_epoch, last_epoch, previous_from_last_epoch
  657. );
  658. for (index, participant) in self.consensus.participants.clone().iter() {
  659. match participant.voted {
  660. Some(epoch) => {
  661. if epoch < last_epoch {
  662. warn!(
  663. "refresh_participants(): Inactive participant: {:?} (joined {:?}, voted {:?})",
  664. participant.address.to_string(),
  665. participant.joined,
  666. participant.voted
  667. );
  668. inactive.push(*index);
  669. }
  670. }
  671. None => {
  672. if (previous_epoch == last_epoch && participant.joined < previous_epoch) ||
  673. (previous_epoch != last_epoch &&
  674. participant.joined < previous_from_last_epoch)
  675. {
  676. warn!(
  677. "refresh_participants(): Inactive participant: {:?} (joined {:?}, voted {:?})",
  678. participant.address.to_string(),
  679. participant.joined,
  680. participant.voted
  681. );
  682. inactive.push(*index);
  683. }
  684. }
  685. }
  686. }
  687. for index in inactive {
  688. self.consensus.participants.remove(&index);
  689. }
  690. if self.consensus.participants.is_empty() {
  691. // If no nodes are active, node becomes a single node network.
  692. let participant = Participant::new(self.address, self.current_epoch());
  693. self.consensus.participants.insert(participant.address, participant);
  694. }
  695. self.consensus.refreshed = epoch;
  696. Ok(())
  697. }
  698. /// Utility function to reset the current consensus state.
  699. pub fn reset_consensus_state(&mut self) -> Result<()> {
  700. let genesis_ts = self.consensus.genesis_ts;
  701. let genesis_block = self.consensus.genesis_block;
  702. let consensus = ConsensusState {
  703. genesis_ts,
  704. genesis_block,
  705. proposals: vec![],
  706. orphan_votes: vec![],
  707. participants: BTreeMap::new(),
  708. pending_participants: vec![],
  709. refreshed: 0,
  710. };
  711. self.consensus = consensus;
  712. Ok(())
  713. }
  714. // ==========================
  715. // State transition functions
  716. // ==========================
  717. /// Validate state transitions for given transactions and state and
  718. /// return a vector of [`StateUpdate`]
  719. pub fn validate_state_transitions(state: MemoryState, txs: &[Tx]) -> Result<Vec<StateUpdate>> {
  720. let mut ret = vec![];
  721. let mut st = state;
  722. for (i, tx) in txs.iter().enumerate() {
  723. let update = match state_transition(&st, tx.0.clone()) {
  724. Ok(v) => v,
  725. Err(e) => {
  726. warn!("validate_state_transition(): Failed for tx {}: {}", i, e);
  727. return Err(e.into())
  728. }
  729. };
  730. st.apply(update.clone());
  731. ret.push(update);
  732. }
  733. Ok(ret)
  734. }
  735. /// Apply a vector of [`StateUpdate`] to the canonical state.
  736. pub async fn update_canon_state(
  737. &self,
  738. updates: Vec<StateUpdate>,
  739. notify: Option<async_channel::Sender<(PublicKey, u64)>>,
  740. ) -> Result<()> {
  741. let secret_keys: Vec<SecretKey> =
  742. self.client.get_keypairs().await?.iter().map(|x| x.secret).collect();
  743. debug!("update_canon_state(): Acquiring state machine lock");
  744. let mut state = self.state_machine.lock().await;
  745. for update in updates {
  746. state
  747. .apply(
  748. update,
  749. secret_keys.clone(),
  750. notify.clone(),
  751. self.client.wallet.clone(),
  752. self.client.tokenlist.clone(),
  753. )
  754. .await?;
  755. }
  756. drop(state);
  757. debug!("update_canon_state(): Dropped state machine lock");
  758. debug!("update_canon_state(): Successfully applied state updates");
  759. Ok(())
  760. }
  761. }