|  | 
| 14 | 14 | // You should have received a copy of the GNU Affero General Public License | 
| 15 | 15 | // along with this program.  If not, see <https://www.gnu.org/licenses/>. | 
| 16 | 16 | 
 | 
|  | 17 | +use std::cmp::Ordering; | 
| 17 | 18 | use std::iter::Iterator; | 
| 18 | 19 | use std::mem; | 
| 19 | 20 | use std::sync::{Arc, Weak}; | 
| @@ -690,34 +691,33 @@ impl Worker { | 
| 690 | 691 |                 cinfo!(ENGINE, "move_to_step: Propose."); | 
| 691 | 692 |                 // If there are multiple proposals, use the first proposal. | 
| 692 | 693 |                 if let Some(hash) = self.votes.get_block_hashes(&vote_step).first() { | 
| 693 |  | -                    if self.client().block(&BlockId::Hash(*hash)).is_some() { | 
| 694 |  | -                        self.proposal = Proposal::new_imported(*hash); | 
| 695 |  | -                        self.move_to_step(TendermintState::Prevote, is_restoring); | 
| 696 |  | -                    } else { | 
|  | 694 | +                    if self.client().block(&BlockId::Hash(*hash)).is_none() { | 
| 697 | 695 |                         cwarn!(ENGINE, "Proposal is received but not imported"); | 
| 698 | 696 |                         // Proposal is received but is not verified yet. | 
| 699 | 697 |                         // Wait for verification. | 
| 700 | 698 |                         return | 
| 701 | 699 |                     } | 
| 702 |  | -                } else { | 
| 703 |  | -                    let parent_block_hash = self.prev_block_hash(); | 
| 704 |  | -                    if self.is_signer_proposer(&parent_block_hash) { | 
| 705 |  | -                        if let TwoThirdsMajority::Lock(lock_view, locked_block_hash) = self.last_two_thirds_majority { | 
| 706 |  | -                            cinfo!(ENGINE, "I am a proposer, I'll re-propose a locked block"); | 
| 707 |  | -                            match self.locked_proposal_block(lock_view, locked_block_hash) { | 
| 708 |  | -                                Ok(block) => self.repropose_block(block), | 
| 709 |  | -                                Err(error_msg) => cwarn!(ENGINE, "{}", error_msg), | 
| 710 |  | -                            } | 
| 711 |  | -                        } else { | 
| 712 |  | -                            cinfo!(ENGINE, "I am a proposer, I'll create a block"); | 
| 713 |  | -                            self.update_sealing(parent_block_hash); | 
| 714 |  | -                            self.step = TendermintState::ProposeWaitBlockGeneration { | 
| 715 |  | -                                parent_hash: parent_block_hash, | 
| 716 |  | -                            }; | 
| 717 |  | -                        } | 
| 718 |  | -                    } else { | 
| 719 |  | -                        self.request_proposal_to_any(vote_step.height, vote_step.view); | 
|  | 700 | +                    self.proposal = Proposal::new_imported(*hash); | 
|  | 701 | +                    self.move_to_step(TendermintState::Prevote, is_restoring); | 
|  | 702 | +                    return | 
|  | 703 | +                } | 
|  | 704 | +                let parent_block_hash = self.prev_block_hash(); | 
|  | 705 | +                if !self.is_signer_proposer(&parent_block_hash) { | 
|  | 706 | +                    self.request_proposal_to_any(vote_step.height, vote_step.view); | 
|  | 707 | +                    return | 
|  | 708 | +                } | 
|  | 709 | +                if let TwoThirdsMajority::Lock(lock_view, locked_block_hash) = self.last_two_thirds_majority { | 
|  | 710 | +                    cinfo!(ENGINE, "I am a proposer, I'll re-propose a locked block"); | 
|  | 711 | +                    match self.locked_proposal_block(lock_view, locked_block_hash) { | 
|  | 712 | +                        Ok(block) => self.repropose_block(block), | 
|  | 713 | +                        Err(error_msg) => cwarn!(ENGINE, "{}", error_msg), | 
| 720 | 714 |                     } | 
|  | 715 | +                } else { | 
|  | 716 | +                    cinfo!(ENGINE, "I am a proposer, I'll create a block"); | 
|  | 717 | +                    self.update_sealing(parent_block_hash); | 
|  | 718 | +                    self.step = TendermintState::ProposeWaitBlockGeneration { | 
|  | 719 | +                        parent_hash: parent_block_hash, | 
|  | 720 | +                    }; | 
| 721 | 721 |                 } | 
| 722 | 722 |             } | 
| 723 | 723 |             Step::Prevote => { | 
| @@ -1562,7 +1562,7 @@ impl Worker { | 
| 1562 | 1562 |             on, | 
| 1563 | 1563 |         }; | 
| 1564 | 1564 | 
 | 
| 1565 |  | -        self.votes.collect(vote.clone()).expect("Must not attempt double vote on proposal");; | 
|  | 1565 | +        self.votes.collect(vote.clone()).expect("Must not attempt double vote on proposal"); | 
| 1566 | 1566 |         cinfo!(ENGINE, "Voted {:?} as {}th proposer.", vote, signer_index); | 
| 1567 | 1567 |         Ok(vote) | 
| 1568 | 1568 |     } | 
| @@ -1811,7 +1811,7 @@ impl Worker { | 
| 1811 | 1811 |                 ); | 
| 1812 | 1812 |             } | 
| 1813 | 1813 | 
 | 
| 1814 |  | -            if let Err(double) = self.votes.collect(message.clone()) { | 
|  | 1814 | +            if let Err(double) = self.votes.collect(message) { | 
| 1815 | 1815 |                 cerror!(ENGINE, "Double Vote found {:?}", double); | 
| 1816 | 1816 |                 self.report_double_vote(&double); | 
| 1817 | 1817 |                 return None | 
| @@ -1869,17 +1869,15 @@ impl Worker { | 
| 1869 | 1869 | 
 | 
| 1870 | 1870 |         let current_step = current_vote_step.step; | 
| 1871 | 1871 |         if current_step == Step::Prevote || current_step == Step::Precommit { | 
| 1872 |  | -            let peer_known_votes = if current_vote_step == peer_vote_step { | 
| 1873 |  | -                peer_known_votes | 
| 1874 |  | -            } else if current_vote_step < peer_vote_step { | 
|  | 1872 | +            let peer_known_votes = match current_vote_step.cmp(&peer_vote_step) { | 
|  | 1873 | +                Ordering::Equal => peer_known_votes, | 
| 1875 | 1874 |                 // We don't know which votes peer has. | 
| 1876 | 1875 |                 // However the peer knows more than 2/3 of votes. | 
| 1877 | 1876 |                 // So request all votes. | 
| 1878 |  | -                BitSet::all_set() | 
| 1879 |  | -            } else { | 
|  | 1877 | +                Ordering::Less => BitSet::all_set(), | 
| 1880 | 1878 |                 // If peer's state is less than my state, | 
| 1881 | 1879 |                 // the peer does not know any useful votes. | 
| 1882 |  | -                BitSet::new() | 
|  | 1880 | +                Ordering::Greater => BitSet::new(), | 
| 1883 | 1881 |             }; | 
| 1884 | 1882 | 
 | 
| 1885 | 1883 |             let difference = &peer_known_votes - &self.votes_received; | 
| @@ -1969,45 +1967,47 @@ impl Worker { | 
| 1969 | 1967 |             return | 
| 1970 | 1968 |         } | 
| 1971 | 1969 | 
 | 
| 1972 |  | -        if height == self.height - 1 { | 
| 1973 |  | -            let block = self.client().block(&height.into()).expect("Parent block should exist"); | 
| 1974 |  | -            let block_hash = block.hash(); | 
| 1975 |  | -            let finalized_view = self.finalized_view_of_previous_block; | 
| 1976 |  | - | 
| 1977 |  | -            let votes = self | 
| 1978 |  | -                .votes | 
| 1979 |  | -                .get_all_votes_in_round(&VoteStep { | 
| 1980 |  | -                    height, | 
| 1981 |  | -                    view: finalized_view, | 
| 1982 |  | -                    step: Step::Precommit, | 
| 1983 |  | -                }) | 
| 1984 |  | -                .into_iter() | 
| 1985 |  | -                .filter(|vote| vote.on.block_hash == Some(block_hash)) | 
| 1986 |  | -                .collect(); | 
| 1987 |  | - | 
| 1988 |  | -            self.send_commit(block, votes, &result); | 
| 1989 |  | -        } else if height < self.height - 1 { | 
| 1990 |  | -            let block = self.client().block(&height.into()).expect("Parent block should exist"); | 
| 1991 |  | -            let child_block = self.client().block(&(height + 1).into()).expect("Parent block should exist"); | 
| 1992 |  | -            let child_block_header_seal = child_block.header().seal(); | 
| 1993 |  | -            let child_block_seal_view = TendermintSealView::new(&child_block_header_seal); | 
| 1994 |  | -            let parent_block_finalized_view = | 
| 1995 |  | -                child_block_seal_view.parent_block_finalized_view().expect("Verified block"); | 
| 1996 |  | -            let on = VoteOn { | 
| 1997 |  | -                step: VoteStep::new(height, parent_block_finalized_view, Step::Precommit), | 
| 1998 |  | -                block_hash: Some(block.hash()), | 
| 1999 |  | -            }; | 
| 2000 |  | -            let mut votes = Vec::new(); | 
| 2001 |  | -            for (index, signature) in child_block_seal_view.signatures().expect("The block is verified") { | 
| 2002 |  | -                let message = ConsensusMessage { | 
| 2003 |  | -                    signature, | 
| 2004 |  | -                    signer_index: index, | 
| 2005 |  | -                    on: on.clone(), | 
|  | 1970 | +        match height.cmp(&(self.height - 1)) { | 
|  | 1971 | +            Ordering::Equal => { | 
|  | 1972 | +                let block = self.client().block(&height.into()).expect("Parent block should exist"); | 
|  | 1973 | +                let block_hash = block.hash(); | 
|  | 1974 | +                let finalized_view = self.finalized_view_of_previous_block; | 
|  | 1975 | + | 
|  | 1976 | +                let votes = self | 
|  | 1977 | +                    .votes | 
|  | 1978 | +                    .get_all_votes_in_round(&VoteStep { | 
|  | 1979 | +                        height, | 
|  | 1980 | +                        view: finalized_view, | 
|  | 1981 | +                        step: Step::Precommit, | 
|  | 1982 | +                    }) | 
|  | 1983 | +                    .into_iter() | 
|  | 1984 | +                    .filter(|vote| vote.on.block_hash == Some(block_hash)) | 
|  | 1985 | +                    .collect(); | 
|  | 1986 | + | 
|  | 1987 | +                self.send_commit(block, votes, &result); | 
|  | 1988 | +            } | 
|  | 1989 | +            Ordering::Less => { | 
|  | 1990 | +                let block = self.client().block(&height.into()).expect("Parent block should exist"); | 
|  | 1991 | +                let child_block = self.client().block(&(height + 1).into()).expect("Parent block should exist"); | 
|  | 1992 | +                let child_block_header_seal = child_block.header().seal(); | 
|  | 1993 | +                let child_block_seal_view = TendermintSealView::new(&child_block_header_seal); | 
|  | 1994 | +                let parent_block_finalized_view = | 
|  | 1995 | +                    child_block_seal_view.parent_block_finalized_view().expect("Verified block"); | 
|  | 1996 | +                let on = VoteOn { | 
|  | 1997 | +                    step: VoteStep::new(height, parent_block_finalized_view, Step::Precommit), | 
|  | 1998 | +                    block_hash: Some(block.hash()), | 
| 2006 | 1999 |                 }; | 
| 2007 |  | -                votes.push(message); | 
|  | 2000 | +                let mut votes = Vec::new(); | 
|  | 2001 | +                for (index, signature) in child_block_seal_view.signatures().expect("The block is verified") { | 
|  | 2002 | +                    let message = ConsensusMessage { | 
|  | 2003 | +                        signature, | 
|  | 2004 | +                        signer_index: index, | 
|  | 2005 | +                        on: on.clone(), | 
|  | 2006 | +                    }; | 
|  | 2007 | +                    votes.push(message); | 
|  | 2008 | +                } | 
| 2008 | 2009 |             } | 
| 2009 |  | - | 
| 2010 |  | -            self.send_commit(block, votes, &result); | 
|  | 2010 | +            Ordering::Greater => {} | 
| 2011 | 2011 |         } | 
| 2012 | 2012 |     } | 
| 2013 | 2013 | 
 | 
| @@ -2049,23 +2049,27 @@ impl Worker { | 
| 2049 | 2049 |             return None | 
| 2050 | 2050 |         } | 
| 2051 | 2051 | 
 | 
| 2052 |  | -        if commit_height < self.height { | 
| 2053 |  | -            cdebug!( | 
| 2054 |  | -                ENGINE, | 
| 2055 |  | -                "Received commit message is old. Current height is {} but commit messages is for height {}", | 
| 2056 |  | -                self.height, | 
| 2057 |  | -                commit_height, | 
| 2058 |  | -            ); | 
| 2059 |  | -            return None | 
| 2060 |  | -        } else if commit_height > self.height { | 
| 2061 |  | -            cwarn!( | 
| 2062 |  | -                ENGINE, | 
| 2063 |  | -                "Invalid commit message received: precommit on height {} but current height is {}", | 
| 2064 |  | -                commit_height, | 
| 2065 |  | -                self.height | 
| 2066 |  | -            ); | 
| 2067 |  | -            return None | 
| 2068 |  | -        } | 
|  | 2052 | +        match commit_height.cmp(&self.height) { | 
|  | 2053 | +            Ordering::Less => { | 
|  | 2054 | +                cdebug!( | 
|  | 2055 | +                    ENGINE, | 
|  | 2056 | +                    "Received commit message is old. Current height is {} but commit messages is for height {}", | 
|  | 2057 | +                    self.height, | 
|  | 2058 | +                    commit_height, | 
|  | 2059 | +                ); | 
|  | 2060 | +                return None | 
|  | 2061 | +            } | 
|  | 2062 | +            Ordering::Greater => { | 
|  | 2063 | +                cwarn!( | 
|  | 2064 | +                    ENGINE, | 
|  | 2065 | +                    "Invalid commit message received: precommit on height {} but current height is {}", | 
|  | 2066 | +                    commit_height, | 
|  | 2067 | +                    self.height | 
|  | 2068 | +                ); | 
|  | 2069 | +                return None | 
|  | 2070 | +            } | 
|  | 2071 | +            Ordering::Equal => {} | 
|  | 2072 | +        }; | 
| 2069 | 2073 | 
 | 
| 2070 | 2074 |         let prev_block_hash = self | 
| 2071 | 2075 |             .client() | 
|  | 
0 commit comments