client invalidateheader and resetchainhead (#3618)

* wip - "reset_head" via owner api functionality

* jsonrpc pass hash in as a string

* sort of works

* not a reorg if we simply accept several blocks at once

* remember to reset header MMR separately
as it is readonly when interacting with txhashset extension

* basic client integration
needs error handling etc.

* reset sync status when reset chain head

* track "denylist" (todo) and validate headers against this via the ctx

* track denylist (header hashes) in chain itself

* header denylist in play

* expose invalidateheader as client cmd

* rework reset_chain_head - rewind txhashset then header MMR
This commit is contained in:
Antioch Peverell
2021-04-29 11:05:05 +01:00
committed by GitHub
parent 9e27e6f9d3
commit 89c06ddab7
10 changed files with 288 additions and 46 deletions
+27 -4
View File
@@ -14,7 +14,7 @@
use super::utils::{get_output, get_output_v2, w};
use crate::chain;
use crate::core::core::hash::Hashed;
use crate::core::core::hash::{Hash, Hashed};
use crate::rest::*;
use crate::router::{Handler, ResponseFuture};
use crate::types::*;
@@ -72,6 +72,29 @@ impl Handler for ChainValidationHandler {
}
}
pub struct ChainResetHandler {
pub chain: Weak<chain::Chain>,
pub sync_state: Weak<chain::SyncState>,
}
impl ChainResetHandler {
pub fn reset_chain_head(&self, hash: Hash) -> Result<(), Error> {
let chain = w(&self.chain)?;
let header = chain.get_block_header(&hash)?;
chain.reset_chain_head(&header)?;
// Reset the sync status and clear out any sync error.
w(&self.sync_state)?.reset();
Ok(())
}
pub fn invalidate_header(&self, hash: Hash) -> Result<(), Error> {
let chain = w(&self.chain)?;
chain.invalidate_header(hash)?;
Ok(())
}
}
/// Chain compaction handler. Trigger a compaction of the chain state to regain
/// storage space.
/// POST /v1/chain/compact
@@ -81,9 +104,9 @@ pub struct ChainCompactHandler {
impl ChainCompactHandler {
pub fn compact_chain(&self) -> Result<(), Error> {
w(&self.chain)?
.compact()
.map_err(|_| ErrorKind::Internal("chain error".to_owned()).into())
let chain = w(&self.chain)?;
chain.compact()?;
Ok(())
}
}
+22 -1
View File
@@ -15,7 +15,8 @@
//! Owner API External Definition
use crate::chain::{Chain, SyncState};
use crate::handlers::chain_api::{ChainCompactHandler, ChainValidationHandler};
use crate::core::core::hash::Hash;
use crate::handlers::chain_api::{ChainCompactHandler, ChainResetHandler, ChainValidationHandler};
use crate::handlers::peers_api::{PeerHandler, PeersConnectedHandler};
use crate::handlers::server_api::StatusHandler;
use crate::p2p::types::PeerInfoDisplay;
@@ -107,6 +108,26 @@ impl Owner {
chain_compact_handler.compact_chain()
}
pub fn reset_chain_head(&self, hash: String) -> Result<(), Error> {
let hash = Hash::from_hex(&hash)
.map_err(|_| ErrorKind::RequestError("invalid header hash".into()))?;
let handler = ChainResetHandler {
chain: self.chain.clone(),
sync_state: self.sync_state.clone(),
};
handler.reset_chain_head(hash)
}
pub fn invalidate_header(&self, hash: String) -> Result<(), Error> {
let hash = Hash::from_hex(&hash)
.map_err(|_| ErrorKind::RequestError("invalid header hash".into()))?;
let handler = ChainResetHandler {
chain: self.chain.clone(),
sync_state: self.sync_state.clone(),
};
handler.invalidate_header(hash)
}
/// Retrieves information about stored peers.
/// If `None` is provided, will list all stored peers.
///
+14 -2
View File
@@ -132,6 +132,10 @@ pub trait OwnerRpc: Sync + Send {
*/
fn compact_chain(&self) -> Result<(), ErrorKind>;
fn reset_chain_head(&self, hash: String) -> Result<(), ErrorKind>;
fn invalidate_header(&self, hash: String) -> Result<(), ErrorKind>;
/**
Networked version of [Owner::get_peers](struct.Owner.html#method.get_peers).
@@ -363,6 +367,14 @@ impl OwnerRpc for Owner {
Owner::validate_chain(self).map_err(|e| e.kind().clone())
}
fn reset_chain_head(&self, hash: String) -> Result<(), ErrorKind> {
Owner::reset_chain_head(self, hash).map_err(|e| e.kind().clone())
}
fn invalidate_header(&self, hash: String) -> Result<(), ErrorKind> {
Owner::invalidate_header(self, hash).map_err(|e| e.kind().clone())
}
fn compact_chain(&self) -> Result<(), ErrorKind> {
Owner::compact_chain(self).map_err(|e| e.kind().clone())
}
@@ -391,7 +403,7 @@ macro_rules! doctest_helper_json_rpc_owner_assert_response {
// create temporary grin server, run jsonrpc request on node api, delete server, return
// json response.
{
{
/*use grin_servers::test_framework::framework::run_doctest;
use grin_util as util;
use serde_json;
@@ -425,6 +437,6 @@ macro_rules! doctest_helper_json_rpc_owner_assert_response {
serde_json::to_string_pretty(&expected_response).unwrap()
);
}*/
}
}
};
}