header methods
This commit is contained in:
parent
03c9760de2
commit
00a3619392
@ -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::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user