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:
@@ -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
@@ -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
@@ -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()
|
||||
);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user