header methods

This commit is contained in:
keorn 2016-11-02 17:42:56 +00:00
parent 03c9760de2
commit 00a3619392

View File

@ -14,14 +14,14 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>. // along with Parity. If not, see <http://www.gnu.org/licenses/>.
//! A blockchain engine that supports a basic, non-BFT proof-of-authority. //! A blockchain engine that supports a non-instant BFT proof-of-authority.
use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering}; use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
use std::sync::Weak; use std::sync::Weak;
use std::time::{UNIX_EPOCH, Duration}; use std::time::{UNIX_EPOCH, Duration};
use util::*; use util::*;
use ethkey::verify_address; use ethkey::{verify_address, Signature};
use rlp::{UntrustedRlp, View, encode, decode}; use rlp::{UntrustedRlp, View, encode};
use account_provider::AccountProvider; use account_provider::AccountProvider;
use block::*; use block::*;
use spec::CommonParams; use spec::CommonParams;
@ -71,6 +71,17 @@ pub struct AuthorityRound {
step: AtomicUsize step: AtomicUsize
} }
impl Header {
fn step(&self) -> Result<usize, ::rlp::DecoderError> {
UntrustedRlp::new(&self.seal()[0]).as_val()
}
fn signature(&self) -> Result<Signature, ::rlp::DecoderError> {
UntrustedRlp::new(&self.seal()[1]).as_val::<H520>().map(Into::into)
}
}
trait AsMillis { trait AsMillis {
fn as_millis(&self) -> u64; fn as_millis(&self) -> u64;
} }
@ -202,12 +213,13 @@ impl Engine for AuthorityRound {
if let Some(ap) = accounts { if let Some(ap) = accounts {
// Account should be permanently unlocked, otherwise sealing will fail. // Account should be permanently unlocked, otherwise sealing will fail.
if let Ok(signature) = ap.sign(*header.author(), None, header.bare_hash()) { if let Ok(signature) = ap.sign(*header.author(), None, header.bare_hash()) {
trace!(target: "poa", "generate_seal: Issuing a block for step {}.", step);
return Some(vec![encode(&step).to_vec(), encode(&(&*signature as &[u8])).to_vec()]); return Some(vec![encode(&step).to_vec(), encode(&(&*signature as &[u8])).to_vec()]);
} else { } else {
trace!(target: "poa", "generate_seal: FAIL: accounts secret key unavailable"); trace!(target: "poa", "generate_seal: FAIL: Accounts secret key unavailable.");
} }
} else { } else {
trace!(target: "poa", "generate_seal: FAIL: accounts not provided"); trace!(target: "poa", "generate_seal: FAIL: Accounts not provided.");
} }
} }
None None
@ -227,10 +239,10 @@ impl Engine for AuthorityRound {
/// Check if the signature belongs to the correct proposer. /// Check if the signature belongs to the correct proposer.
fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> { fn verify_block_unordered(&self, header: &Header, _block: Option<&[u8]>) -> Result<(), Error> {
let step = try!(UntrustedRlp::new(&header.seal()[0]).as_val::<usize>()); let header_step = try!(header.step());
if step <= self.step() { // Give one step slack if step is lagging, double vote is still not possible.
let sig = try!(UntrustedRlp::new(&header.seal()[1]).as_val::<H520>()); if header_step <= self.step() + 1 {
let ok_sig = try!(verify_address(self.step_proposer(step), &sig.into(), &header.bare_hash())); let ok_sig = try!(verify_address(self.step_proposer(header_step), &try!(header.signature()), &header.bare_hash()));
if ok_sig { if ok_sig {
Ok(()) Ok(())
} else { } else {
@ -250,9 +262,7 @@ impl Engine for AuthorityRound {
} }
// Check if parent is from a previous step. // Check if parent is from a previous step.
let parent_step = try!(UntrustedRlp::new(&parent.seal()[0]).as_val::<usize>()); if try!(header.step()) == try!(parent.step()) {
let step = try!(UntrustedRlp::new(&header.seal()[0]).as_val::<usize>());
if step <= parent_step {
try!(Err(BlockError::DoubleVote(header.author().clone()))); try!(Err(BlockError::DoubleVote(header.author().clone())));
} }
@ -284,13 +294,6 @@ impl Engine for AuthorityRound {
} }
} }
impl Header {
/// Get the none field of the header.
pub fn signature(&self) -> H520 {
decode(&self.seal()[0])
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use common::*; use common::*;