Makes eth_mining to return False if not is not allowed to seal (#581)

This commit is contained in:
Rim Rakhimov 2021-12-10 14:25:39 +03:00 committed by GitHub
parent f703d01f23
commit 63bab44e3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 111 additions and 2 deletions

View File

@ -1557,6 +1557,43 @@ impl Engine<EthereumMachine> for AuthorityRound {
}
}
// Mostly is the same as `fn sealing_state(&self)` except that it does not
// check whether the node is a step proposer.
fn is_allowed_to_seal(&self) -> bool {
let our_addr = match *self.signer.read() {
Some(ref signer) => signer.address(),
None => return false,
};
let client = match self.upgrade_client_or("Not preparing block") {
Ok(client) => client,
Err(_) => return false,
};
let parent = match client.as_full_client() {
Some(full_client) => full_client.best_block_header(),
None => {
return false;
}
};
let validators = if self.immediate_transitions {
CowLike::Borrowed(&*self.validators)
} else {
let mut epoch_manager = self.epoch_manager.lock();
if !epoch_manager.zoom_to_after(
&*client,
&self.machine,
&*self.validators,
parent.hash(),
) {
return false;
}
CowLike::Owned(epoch_manager.validators().clone())
};
validators.contains(&parent.hash(), &our_addr)
}
fn sealing_state(&self) -> SealingState {
let our_addr = match *self.signer.read() {
Some(ref signer) => signer.address(),

View File

@ -470,6 +470,14 @@ pub trait Engine<M: Machine>: Sync + Send {
/// Register a component which signs consensus messages.
fn set_signer(&self, _signer: Option<Box<dyn EngineSigner>>) {}
/// Returns whether the current node is a validator and
/// actually may seal a block if AuRa engine is used.
///
/// Used by `eth_mining` rpc call.
fn is_allowed_to_seal(&self) -> bool {
true
}
/// Sign using the EngineSigner, to be used for consensus tx signing.
fn sign(&self, _hash: H256) -> Result<Signature, M::Error> {
unimplemented!()

View File

@ -1377,7 +1377,7 @@ impl miner::MinerService for Miner {
}
fn is_currently_sealing(&self) -> bool {
self.sealing.lock().enabled
self.sealing.lock().enabled && self.engine.is_allowed_to_seal()
}
fn work_package<C>(&self, chain: &C) -> Option<(H256, BlockNumber, u64, U256)>
@ -1608,7 +1608,9 @@ mod tests {
use client::{ChainInfo, EachBlockWith, ImportSealedBlock, TestBlockChainClient};
use miner::{MinerService, PendingOrdering};
use test_helpers::{generate_dummy_client, generate_dummy_client_with_spec};
use test_helpers::{
dummy_engine_signer_with_address, generate_dummy_client, generate_dummy_client_with_spec,
};
use types::transaction::{Transaction, TypedTransaction};
#[test]
@ -2078,6 +2080,31 @@ mod tests {
assert!(miner.is_currently_sealing());
}
#[test]
fn should_not_mine_if_is_not_allowed_to_seal() {
let spec = Spec::new_test_round();
let miner = Miner::new_for_tests_force_sealing(&spec, None, true);
assert!(!miner.is_currently_sealing());
}
#[test]
fn should_mine_if_is_allowed_to_seal() {
let verifier: Address = [
0x7d, 0x57, 0x7a, 0x59, 0x7b, 0x27, 0x42, 0xb4, 0x98, 0xcb, 0x5c, 0xf0, 0xc2, 0x6c,
0xdc, 0xd7, 0x26, 0xd3, 0x9e, 0x6e,
]
.into();
let spec = Spec::new_test_round();
let client: Arc<dyn EngineClient> = generate_dummy_client(2);
let miner = Miner::new_for_tests_force_sealing(&spec, None, true);
miner.engine.register_client(Arc::downgrade(&client));
miner.set_author(Author::Sealer(dummy_engine_signer_with_address(verifier)));
assert!(miner.is_currently_sealing());
}
#[test]
fn should_set_new_minimum_gas_price() {
// Creates a new GasPricer::Fixed behind the scenes

View File

@ -46,6 +46,8 @@ use block::{Drain, OpenBlock};
use client::{
ChainInfo, ChainMessageType, ChainNotify, Client, ClientConfig, ImportBlock, PrepareOpenBlock,
};
use engines::EngineSigner;
use ethjson::crypto::publickey::{Public, Signature};
use factory::Factories;
use miner::Miner;
use spec::Spec;
@ -644,3 +646,38 @@ impl ChainNotify for TestNotify {
self.messages.write().push(data);
}
}
/// Returns engine signer with specified address
pub fn dummy_engine_signer_with_address(addr: Address) -> Box<dyn EngineSigner> {
struct TestEngineSigner(Address);
impl TestEngineSigner {
fn with_address(addr: Address) -> Self {
Self(addr)
}
}
impl EngineSigner for TestEngineSigner {
fn sign(&self, _hash: H256) -> Result<Signature, ethjson::crypto::publickey::Error> {
unimplemented!()
}
fn address(&self) -> Address {
self.0
}
fn decrypt(
&self,
_auth_data: &[u8],
_cipher: &[u8],
) -> Result<Vec<u8>, parity_crypto::publickey::Error> {
unimplemented!()
}
fn public(&self) -> Option<Public> {
unimplemented!()
}
}
Box::new(TestEngineSigner::with_address(addr))
}