mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 08:51:08 +03:00
Reduce number of unwwaps in api crate (#2681)
* Reduce number of unwwaps in api crate * Format use section
This commit is contained in:
parent
2b218f2dc3
commit
7fad5b040f
17 changed files with 165 additions and 123 deletions
|
@ -13,19 +13,25 @@
|
|||
// limitations under the License.
|
||||
|
||||
use crate::router::{Handler, HandlerObj, ResponseFuture};
|
||||
use crate::web::response;
|
||||
use futures::future::ok;
|
||||
use hyper::header::{HeaderValue, AUTHORIZATION, WWW_AUTHENTICATE};
|
||||
use hyper::{Body, Request, Response, StatusCode};
|
||||
use ring::constant_time::verify_slices_are_equal;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref GRIN_BASIC_REALM: HeaderValue =
|
||||
HeaderValue::from_str("Basic realm=GrinAPI").unwrap();
|
||||
}
|
||||
|
||||
// Basic Authentication Middleware
|
||||
pub struct BasicAuthMiddleware {
|
||||
api_basic_auth: String,
|
||||
basic_realm: String,
|
||||
basic_realm: &'static HeaderValue,
|
||||
}
|
||||
|
||||
impl BasicAuthMiddleware {
|
||||
pub fn new(api_basic_auth: String, basic_realm: String) -> BasicAuthMiddleware {
|
||||
pub fn new(api_basic_auth: String, basic_realm: &'static HeaderValue) -> BasicAuthMiddleware {
|
||||
BasicAuthMiddleware {
|
||||
api_basic_auth,
|
||||
basic_realm,
|
||||
|
@ -39,8 +45,12 @@ impl Handler for BasicAuthMiddleware {
|
|||
req: Request<Body>,
|
||||
mut handlers: Box<dyn Iterator<Item = HandlerObj>>,
|
||||
) -> ResponseFuture {
|
||||
let next_handler = match handlers.next() {
|
||||
Some(h) => h,
|
||||
None => return response(StatusCode::INTERNAL_SERVER_ERROR, "no handler found"),
|
||||
};
|
||||
if req.method().as_str() == "OPTIONS" {
|
||||
return handlers.next().unwrap().call(req, handlers);
|
||||
return next_handler.call(req, handlers);
|
||||
}
|
||||
if req.headers().contains_key(AUTHORIZATION)
|
||||
&& verify_slices_are_equal(
|
||||
|
@ -49,7 +59,7 @@ impl Handler for BasicAuthMiddleware {
|
|||
)
|
||||
.is_ok()
|
||||
{
|
||||
handlers.next().unwrap().call(req, handlers)
|
||||
next_handler.call(req, handlers)
|
||||
} else {
|
||||
// Unauthorized 401
|
||||
unauthorized_response(&self.basic_realm)
|
||||
|
@ -57,13 +67,10 @@ impl Handler for BasicAuthMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
fn unauthorized_response(basic_realm: &str) -> ResponseFuture {
|
||||
fn unauthorized_response(basic_realm: &HeaderValue) -> ResponseFuture {
|
||||
let response = Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.header(
|
||||
WWW_AUTHENTICATE,
|
||||
HeaderValue::from_str(basic_realm).unwrap(),
|
||||
)
|
||||
.header(WWW_AUTHENTICATE, basic_realm)
|
||||
.body(Body::empty())
|
||||
.unwrap();
|
||||
Box::new(ok(response))
|
||||
|
|
|
@ -136,9 +136,8 @@ fn build_request<'a>(
|
|||
.into()
|
||||
})?;
|
||||
let mut builder = Request::builder();
|
||||
if api_secret.is_some() {
|
||||
let basic_auth =
|
||||
"Basic ".to_string() + &to_base64(&("grin:".to_string() + &api_secret.unwrap()));
|
||||
if let Some(api_secret) = api_secret {
|
||||
let basic_auth = format!("Basic {}", to_base64(&format!("grin:{}", api_secret)));
|
||||
builder.header(AUTHORIZATION, basic_auth);
|
||||
}
|
||||
|
||||
|
@ -224,6 +223,7 @@ fn send_request_async(req: Request<Body>) -> Box<dyn Future<Item = String, Error
|
|||
|
||||
fn send_request(req: Request<Body>) -> Result<String, Error> {
|
||||
let task = send_request_async(req);
|
||||
let mut rt = Runtime::new().unwrap();
|
||||
let mut rt =
|
||||
Runtime::new().context(ErrorKind::Internal("can't create Tokio runtime".to_owned()))?;
|
||||
Ok(rt.block_on(task)?)
|
||||
}
|
||||
|
|
|
@ -20,39 +20,26 @@ mod server_api;
|
|||
mod transactions_api;
|
||||
mod utils;
|
||||
|
||||
use crate::router::{Router, RouterError};
|
||||
|
||||
// Server
|
||||
use self::server_api::IndexHandler;
|
||||
use self::server_api::StatusHandler;
|
||||
|
||||
// Blocks
|
||||
use self::blocks_api::BlockHandler;
|
||||
use self::blocks_api::HeaderHandler;
|
||||
|
||||
// TX Set
|
||||
use self::transactions_api::TxHashSetHandler;
|
||||
|
||||
// Chain
|
||||
use self::chain_api::ChainCompactHandler;
|
||||
use self::chain_api::ChainHandler;
|
||||
use self::chain_api::ChainValidationHandler;
|
||||
use self::chain_api::OutputHandler;
|
||||
|
||||
// Pool Handlers
|
||||
use self::pool_api::PoolInfoHandler;
|
||||
use self::pool_api::PoolPushHandler;
|
||||
|
||||
// Peers
|
||||
use self::peers_api::PeerHandler;
|
||||
use self::peers_api::PeersAllHandler;
|
||||
use self::peers_api::PeersConnectedHandler;
|
||||
|
||||
use crate::auth::BasicAuthMiddleware;
|
||||
use self::pool_api::PoolInfoHandler;
|
||||
use self::pool_api::PoolPushHandler;
|
||||
use self::server_api::IndexHandler;
|
||||
use self::server_api::StatusHandler;
|
||||
use self::transactions_api::TxHashSetHandler;
|
||||
use crate::auth::{BasicAuthMiddleware, GRIN_BASIC_REALM};
|
||||
use crate::chain;
|
||||
use crate::p2p;
|
||||
use crate::pool;
|
||||
use crate::rest::*;
|
||||
use crate::router::{Router, RouterError};
|
||||
use crate::util;
|
||||
use crate::util::RwLock;
|
||||
use std::net::SocketAddr;
|
||||
|
@ -76,11 +63,10 @@ pub fn start_rest_apis(
|
|||
) -> bool {
|
||||
let mut apis = ApiServer::new();
|
||||
let mut router = build_router(chain, tx_pool, peers).expect("unable to build API router");
|
||||
if api_secret.is_some() {
|
||||
let api_basic_auth =
|
||||
"Basic ".to_string() + &util::to_base64(&("grin:".to_string() + &api_secret.unwrap()));
|
||||
let basic_realm = "Basic realm=GrinAPI".to_string();
|
||||
let basic_auth_middleware = Arc::new(BasicAuthMiddleware::new(api_basic_auth, basic_realm));
|
||||
if let Some(api_secret) = api_secret {
|
||||
let api_basic_auth = format!("Basic {}", util::to_base64(&format!("grin:{}", api_secret)));
|
||||
let basic_auth_middleware =
|
||||
Arc::new(BasicAuthMiddleware::new(api_basic_auth, &GRIN_BASIC_REALM));
|
||||
router.add_middleware(basic_auth_middleware);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ impl HeaderHandler {
|
|||
return Ok(h);
|
||||
}
|
||||
if let Ok(height) = input.parse() {
|
||||
match w(&self.chain).get_header_by_height(height) {
|
||||
match w(&self.chain)?.get_header_by_height(height) {
|
||||
Ok(header) => return Ok(BlockHeaderPrintable::from_header(&header)),
|
||||
Err(_) => return Err(ErrorKind::NotFound)?,
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ impl HeaderHandler {
|
|||
let vec = util::from_hex(input)
|
||||
.map_err(|e| ErrorKind::Argument(format!("invalid input: {}", e)))?;
|
||||
let h = Hash::from_vec(&vec);
|
||||
let header = w(&self.chain)
|
||||
let header = w(&self.chain)?
|
||||
.get_block_header(&h)
|
||||
.context(ErrorKind::NotFound)?;
|
||||
Ok(BlockHeaderPrintable::from_header(&header))
|
||||
|
@ -58,7 +58,7 @@ impl HeaderHandler {
|
|||
|
||||
fn get_header_for_output(&self, commit_id: String) -> Result<BlockHeaderPrintable, Error> {
|
||||
let oid = get_output(&self.chain, &commit_id)?.1;
|
||||
match w(&self.chain).get_header_for_output(&oid) {
|
||||
match w(&self.chain)?.get_header_for_output(&oid) {
|
||||
Ok(header) => Ok(BlockHeaderPrintable::from_header(&header)),
|
||||
Err(_) => Err(ErrorKind::NotFound)?,
|
||||
}
|
||||
|
@ -85,22 +85,23 @@ pub struct BlockHandler {
|
|||
|
||||
impl BlockHandler {
|
||||
fn get_block(&self, h: &Hash) -> Result<BlockPrintable, Error> {
|
||||
let block = w(&self.chain).get_block(h).context(ErrorKind::NotFound)?;
|
||||
Ok(BlockPrintable::from_block(&block, w(&self.chain), false))
|
||||
let chain = w(&self.chain)?;
|
||||
let block = chain.get_block(h).context(ErrorKind::NotFound)?;
|
||||
BlockPrintable::from_block(&block, chain, false)
|
||||
.map_err(|_| ErrorKind::Internal("chain error".to_owned()).into())
|
||||
}
|
||||
|
||||
fn get_compact_block(&self, h: &Hash) -> Result<CompactBlockPrintable, Error> {
|
||||
let block = w(&self.chain).get_block(h).context(ErrorKind::NotFound)?;
|
||||
Ok(CompactBlockPrintable::from_compact_block(
|
||||
&block.into(),
|
||||
w(&self.chain),
|
||||
))
|
||||
let chain = w(&self.chain)?;
|
||||
let block = chain.get_block(h).context(ErrorKind::NotFound)?;
|
||||
CompactBlockPrintable::from_compact_block(&block.into(), chain)
|
||||
.map_err(|_| ErrorKind::Internal("chain error".to_owned()).into())
|
||||
}
|
||||
|
||||
// Try to decode the string as a height or a hash.
|
||||
fn parse_input(&self, input: String) -> Result<Hash, Error> {
|
||||
if let Ok(height) = input.parse() {
|
||||
match w(&self.chain).get_header_by_height(height) {
|
||||
match w(&self.chain)?.get_header_by_height(height) {
|
||||
Ok(header) => return Ok(header.hash()),
|
||||
Err(_) => return Err(ErrorKind::NotFound)?,
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ use crate::types::*;
|
|||
use crate::util;
|
||||
use crate::util::secp::pedersen::Commitment;
|
||||
use crate::web::*;
|
||||
use failure::ResultExt;
|
||||
use hyper::{Body, Request, StatusCode};
|
||||
use std::sync::Weak;
|
||||
|
||||
|
@ -32,7 +33,7 @@ pub struct ChainHandler {
|
|||
|
||||
impl ChainHandler {
|
||||
fn get_tip(&self) -> Result<Tip, Error> {
|
||||
let head = w(&self.chain)
|
||||
let head = w(&self.chain)?
|
||||
.head()
|
||||
.map_err(|e| ErrorKind::Internal(format!("can't get head: {}", e)))?;
|
||||
Ok(Tip::from_tip(head))
|
||||
|
@ -53,7 +54,7 @@ pub struct ChainValidationHandler {
|
|||
|
||||
impl Handler for ChainValidationHandler {
|
||||
fn get(&self, _req: Request<Body>) -> ResponseFuture {
|
||||
match w(&self.chain).validate(true) {
|
||||
match w_fut!(&self.chain).validate(true) {
|
||||
Ok(_) => response(StatusCode::OK, "{}"),
|
||||
Err(e) => response(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
|
@ -72,7 +73,7 @@ pub struct ChainCompactHandler {
|
|||
|
||||
impl Handler for ChainCompactHandler {
|
||||
fn post(&self, _req: Request<Body>) -> ResponseFuture {
|
||||
match w(&self.chain).compact() {
|
||||
match w_fut!(&self.chain).compact() {
|
||||
Ok(_) => response(StatusCode::OK, "{}"),
|
||||
Err(e) => response(
|
||||
StatusCode::INTERNAL_SERVER_ERROR,
|
||||
|
@ -118,13 +119,14 @@ impl OutputHandler {
|
|||
commitments: Vec<Commitment>,
|
||||
include_proof: bool,
|
||||
) -> Result<BlockOutputs, Error> {
|
||||
let header = w(&self.chain)
|
||||
let header = w(&self.chain)?
|
||||
.get_header_by_height(block_height)
|
||||
.map_err(|_| ErrorKind::NotFound)?;
|
||||
|
||||
// TODO - possible to compact away blocks we care about
|
||||
// in the period between accepting the block and refreshing the wallet
|
||||
let block = w(&self.chain)
|
||||
let chain = w(&self.chain)?;
|
||||
let block = chain
|
||||
.get_block(&header.hash())
|
||||
.map_err(|_| ErrorKind::NotFound)?;
|
||||
let outputs = block
|
||||
|
@ -132,9 +134,10 @@ impl OutputHandler {
|
|||
.iter()
|
||||
.filter(|output| commitments.is_empty() || commitments.contains(&output.commit))
|
||||
.map(|output| {
|
||||
OutputPrintable::from_output(output, w(&self.chain), Some(&header), include_proof)
|
||||
OutputPrintable::from_output(output, chain.clone(), Some(&header), include_proof)
|
||||
})
|
||||
.collect();
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.context(ErrorKind::Internal("cain error".to_owned()))?;
|
||||
|
||||
Ok(BlockOutputs {
|
||||
header: BlockHeaderInfo::from_header(&header),
|
||||
|
|
|
@ -26,7 +26,7 @@ pub struct PeersAllHandler {
|
|||
|
||||
impl Handler for PeersAllHandler {
|
||||
fn get(&self, _req: Request<Body>) -> ResponseFuture {
|
||||
let peers = &w(&self.peers).all_peers();
|
||||
let peers = &w_fut!(&self.peers).all_peers();
|
||||
json_response_pretty(&peers)
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ pub struct PeersConnectedHandler {
|
|||
|
||||
impl Handler for PeersConnectedHandler {
|
||||
fn get(&self, _req: Request<Body>) -> ResponseFuture {
|
||||
let peers: Vec<PeerInfoDisplay> = w(&self.peers)
|
||||
let peers: Vec<PeerInfoDisplay> = w_fut!(&self.peers)
|
||||
.connected_peers()
|
||||
.iter()
|
||||
.map(|p| p.info.clone().into())
|
||||
|
@ -73,7 +73,7 @@ impl Handler for PeerHandler {
|
|||
);
|
||||
}
|
||||
|
||||
match w(&self.peers).get_peer(peer_addr) {
|
||||
match w_fut!(&self.peers).get_peer(peer_addr) {
|
||||
Ok(peer) => json_response(&peer),
|
||||
Err(_) => response(StatusCode::NOT_FOUND, "peer not found"),
|
||||
}
|
||||
|
@ -101,8 +101,8 @@ impl Handler for PeerHandler {
|
|||
};
|
||||
|
||||
match command {
|
||||
"ban" => w(&self.peers).ban_peer(addr, ReasonForBan::ManualBan),
|
||||
"unban" => w(&self.peers).unban_peer(addr),
|
||||
"ban" => w_fut!(&self.peers).ban_peer(addr, ReasonForBan::ManualBan),
|
||||
"unban" => w_fut!(&self.peers).unban_peer(addr),
|
||||
_ => return response(StatusCode::BAD_REQUEST, "invalid command"),
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ use crate::util;
|
|||
use crate::util::RwLock;
|
||||
use crate::web::*;
|
||||
use failure::ResultExt;
|
||||
use futures::future::ok;
|
||||
use futures::future::{err, ok};
|
||||
use futures::Future;
|
||||
use hyper::{Body, Request, StatusCode};
|
||||
use std::sync::Weak;
|
||||
|
@ -37,7 +37,7 @@ pub struct PoolInfoHandler {
|
|||
|
||||
impl Handler for PoolInfoHandler {
|
||||
fn get(&self, _req: Request<Body>) -> ResponseFuture {
|
||||
let pool_arc = w(&self.tx_pool);
|
||||
let pool_arc = w_fut!(&self.tx_pool);
|
||||
let pool = pool_arc.read();
|
||||
|
||||
json_response(&PoolInfo {
|
||||
|
@ -63,7 +63,11 @@ impl PoolPushHandler {
|
|||
let params = QueryParams::from(req.uri().query());
|
||||
|
||||
let fluff = params.get("fluff").is_some();
|
||||
let pool_arc = w(&self.tx_pool).clone();
|
||||
let pool_arc = match w(&self.tx_pool) {
|
||||
//w(&self.tx_pool).clone();
|
||||
Ok(p) => p,
|
||||
Err(e) => return Box::new(err(e)),
|
||||
};
|
||||
|
||||
Box::new(
|
||||
parse_body(req)
|
||||
|
|
|
@ -45,12 +45,12 @@ pub struct StatusHandler {
|
|||
|
||||
impl StatusHandler {
|
||||
fn get_status(&self) -> Result<Status, Error> {
|
||||
let head = w(&self.chain)
|
||||
let head = w(&self.chain)?
|
||||
.head()
|
||||
.map_err(|e| ErrorKind::Internal(format!("can't get head: {}", e)))?;
|
||||
Ok(Status::from_tip_and_peers(
|
||||
head,
|
||||
w(&self.peers).peer_count(),
|
||||
w(&self.peers)?.peer_count(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,23 +45,26 @@ pub struct TxHashSetHandler {
|
|||
|
||||
impl TxHashSetHandler {
|
||||
// gets roots
|
||||
fn get_roots(&self) -> TxHashSet {
|
||||
TxHashSet::from_head(w(&self.chain))
|
||||
fn get_roots(&self) -> Result<TxHashSet, Error> {
|
||||
Ok(TxHashSet::from_head(w(&self.chain)?))
|
||||
}
|
||||
|
||||
// gets last n outputs inserted in to the tree
|
||||
fn get_last_n_output(&self, distance: u64) -> Vec<TxHashSetNode> {
|
||||
TxHashSetNode::get_last_n_output(w(&self.chain), distance)
|
||||
fn get_last_n_output(&self, distance: u64) -> Result<Vec<TxHashSetNode>, Error> {
|
||||
Ok(TxHashSetNode::get_last_n_output(w(&self.chain)?, distance))
|
||||
}
|
||||
|
||||
// gets last n outputs inserted in to the tree
|
||||
fn get_last_n_rangeproof(&self, distance: u64) -> Vec<TxHashSetNode> {
|
||||
TxHashSetNode::get_last_n_rangeproof(w(&self.chain), distance)
|
||||
fn get_last_n_rangeproof(&self, distance: u64) -> Result<Vec<TxHashSetNode>, Error> {
|
||||
Ok(TxHashSetNode::get_last_n_rangeproof(
|
||||
w(&self.chain)?,
|
||||
distance,
|
||||
))
|
||||
}
|
||||
|
||||
// gets last n outputs inserted in to the tree
|
||||
fn get_last_n_kernel(&self, distance: u64) -> Vec<TxHashSetNode> {
|
||||
TxHashSetNode::get_last_n_kernel(w(&self.chain), distance)
|
||||
fn get_last_n_kernel(&self, distance: u64) -> Result<Vec<TxHashSetNode>, Error> {
|
||||
Ok(TxHashSetNode::get_last_n_kernel(w(&self.chain)?, distance))
|
||||
}
|
||||
|
||||
// allows traversal of utxo set
|
||||
|
@ -70,18 +73,21 @@ impl TxHashSetHandler {
|
|||
if max > 1000 {
|
||||
max = 1000;
|
||||
}
|
||||
let outputs = w(&self.chain)
|
||||
let chain = w(&self.chain)?;
|
||||
let outputs = chain
|
||||
.unspent_outputs_by_insertion_index(start_index, max)
|
||||
.context(ErrorKind::NotFound)?;
|
||||
Ok(OutputListing {
|
||||
let out = OutputListing {
|
||||
last_retrieved_index: outputs.0,
|
||||
highest_index: outputs.1,
|
||||
outputs: outputs
|
||||
.2
|
||||
.iter()
|
||||
.map(|x| OutputPrintable::from_output(x, w(&self.chain), None, true))
|
||||
.collect(),
|
||||
})
|
||||
.map(|x| OutputPrintable::from_output(x, chain.clone(), None, true))
|
||||
.collect::<Result<Vec<_>, _>>()
|
||||
.context(ErrorKind::Internal("cain error".to_owned()))?,
|
||||
};
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
// return a dummy output with merkle proof for position filled out
|
||||
|
@ -92,10 +98,9 @@ impl TxHashSetHandler {
|
|||
id
|
||||
)))?;
|
||||
let commit = Commitment::from_vec(c);
|
||||
let output_pos = w(&self.chain)
|
||||
.get_output_pos(&commit)
|
||||
.context(ErrorKind::NotFound)?;
|
||||
let merkle_proof = chain::Chain::get_merkle_proof_for_pos(&w(&self.chain), commit)
|
||||
let chain = w(&self.chain)?;
|
||||
let output_pos = chain.get_output_pos(&commit).context(ErrorKind::NotFound)?;
|
||||
let merkle_proof = chain::Chain::get_merkle_proof_for_pos(&chain, commit)
|
||||
.map_err(|_| ErrorKind::NotFound)?;
|
||||
Ok(OutputPrintable {
|
||||
output_type: OutputType::Coinbase,
|
||||
|
@ -120,10 +125,10 @@ impl Handler for TxHashSetHandler {
|
|||
let id = parse_param_no_err!(params, "id", "".to_owned());
|
||||
|
||||
match right_path_element!(req) {
|
||||
"roots" => json_response_pretty(&self.get_roots()),
|
||||
"lastoutputs" => json_response_pretty(&self.get_last_n_output(last_n)),
|
||||
"lastrangeproofs" => json_response_pretty(&self.get_last_n_rangeproof(last_n)),
|
||||
"lastkernels" => json_response_pretty(&self.get_last_n_kernel(last_n)),
|
||||
"roots" => result_to_response(self.get_roots()),
|
||||
"lastoutputs" => result_to_response(self.get_last_n_output(last_n)),
|
||||
"lastrangeproofs" => result_to_response(self.get_last_n_rangeproof(last_n)),
|
||||
"lastkernels" => result_to_response(self.get_last_n_kernel(last_n)),
|
||||
"outputs" => result_to_response(self.outputs(start_index, max)),
|
||||
"merkleproof" => result_to_response(self.get_merkle_proof_for_output(&id)),
|
||||
_ => response(StatusCode::BAD_REQUEST, ""),
|
||||
|
|
|
@ -24,8 +24,9 @@ use std::sync::{Arc, Weak};
|
|||
// All handlers use `Weak` references instead of `Arc` to avoid cycles that
|
||||
// can never be destroyed. These 2 functions are simple helpers to reduce the
|
||||
// boilerplate of dealing with `Weak`.
|
||||
pub fn w<T>(weak: &Weak<T>) -> Arc<T> {
|
||||
weak.upgrade().unwrap()
|
||||
pub fn w<T>(weak: &Weak<T>) -> Result<Arc<T>, Error> {
|
||||
weak.upgrade()
|
||||
.ok_or_else(|| ErrorKind::Internal("failed to upgrade weak refernce".to_owned()).into())
|
||||
}
|
||||
|
||||
/// Retrieves an output from the chain given a commit id (a tiny bit iteratively)
|
||||
|
@ -48,14 +49,16 @@ pub fn get_output(
|
|||
OutputIdentifier::new(OutputFeatures::Coinbase, &commit),
|
||||
];
|
||||
|
||||
for x in outputs.iter().filter(|x| w(chain).is_unspent(x).is_ok()) {
|
||||
let block_height = w(chain)
|
||||
let chain = w(chain)?;
|
||||
|
||||
for x in outputs.iter().filter(|x| chain.is_unspent(x).is_ok()) {
|
||||
let block_height = chain
|
||||
.get_header_for_output(&x)
|
||||
.context(ErrorKind::Internal(
|
||||
"Can't get header for output".to_owned(),
|
||||
))?
|
||||
.height;
|
||||
let output_pos = w(chain).get_output_pos(&x.commit).unwrap_or(0);
|
||||
let output_pos = chain.get_output_pos(&x.commit).unwrap_or(0);
|
||||
return Ok((Output::new(&commit, block_height, output_pos), x.clone()));
|
||||
}
|
||||
Err(ErrorKind::NotFound)?
|
||||
|
|
|
@ -39,7 +39,7 @@ mod rest;
|
|||
mod router;
|
||||
mod types;
|
||||
|
||||
pub use crate::auth::BasicAuthMiddleware;
|
||||
pub use crate::auth::{BasicAuthMiddleware, GRIN_BASIC_REALM};
|
||||
pub use crate::handlers::start_rest_apis;
|
||||
pub use crate::rest::*;
|
||||
pub use crate::router::*;
|
||||
|
|
|
@ -19,11 +19,12 @@
|
|||
//! register them on a ApiServer.
|
||||
|
||||
use crate::router::{Handler, HandlerObj, ResponseFuture, Router};
|
||||
use crate::web::response;
|
||||
use failure::{Backtrace, Context, Fail, ResultExt};
|
||||
use futures::sync::oneshot;
|
||||
use futures::Stream;
|
||||
use hyper::rt::Future;
|
||||
use hyper::{rt, Body, Request, Server};
|
||||
use hyper::{rt, Body, Request, Server, StatusCode};
|
||||
use rustls;
|
||||
use rustls::internal::pemfile;
|
||||
use std::fmt::{self, Display};
|
||||
|
@ -264,6 +265,9 @@ impl Handler for LoggingMiddleware {
|
|||
mut handlers: Box<dyn Iterator<Item = HandlerObj>>,
|
||||
) -> ResponseFuture {
|
||||
debug!("REST call: {} {}", req.method(), req.uri().path());
|
||||
handlers.next().unwrap().call(req, handlers)
|
||||
match handlers.next() {
|
||||
Some(handler) => handler.call(req, handlers),
|
||||
None => response(StatusCode::INTERNAL_SERVER_ERROR, "no handler found"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -222,7 +222,9 @@ impl<'de> serde::de::Visitor<'de> for PrintableCommitmentVisitor {
|
|||
E: serde::de::Error,
|
||||
{
|
||||
Ok(PrintableCommitment {
|
||||
commit: pedersen::Commitment::from_vec(util::from_hex(String::from(v)).unwrap()),
|
||||
commit: pedersen::Commitment::from_vec(
|
||||
util::from_hex(String::from(v)).map_err(serde::de::Error::custom)?,
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -255,7 +257,7 @@ impl OutputPrintable {
|
|||
chain: Arc<chain::Chain>,
|
||||
block_header: Option<&core::BlockHeader>,
|
||||
include_proof: bool,
|
||||
) -> OutputPrintable {
|
||||
) -> Result<OutputPrintable, chain::Error> {
|
||||
let output_type = if output.is_coinbase() {
|
||||
OutputType::Coinbase
|
||||
} else {
|
||||
|
@ -266,7 +268,7 @@ impl OutputPrintable {
|
|||
let spent = chain.is_unspent(&out_id).is_err();
|
||||
let block_height = match spent {
|
||||
true => None,
|
||||
false => Some(chain.get_header_for_output(&out_id).unwrap().height),
|
||||
false => Some(chain.get_header_for_output(&out_id)?.height),
|
||||
};
|
||||
|
||||
let proof = if include_proof {
|
||||
|
@ -280,13 +282,15 @@ impl OutputPrintable {
|
|||
// We require the rewind() to be stable even after the PMMR is pruned and
|
||||
// compacted so we can still recreate the necessary proof.
|
||||
let mut merkle_proof = None;
|
||||
if output.is_coinbase() && !spent && block_header.is_some() {
|
||||
merkle_proof = chain.get_merkle_proof(&out_id, &block_header.unwrap()).ok()
|
||||
if output.is_coinbase() && !spent {
|
||||
if let Some(block_header) = block_header {
|
||||
merkle_proof = chain.get_merkle_proof(&out_id, &block_header).ok();
|
||||
}
|
||||
};
|
||||
|
||||
let output_pos = chain.get_output_pos(&output.commit).unwrap_or(0);
|
||||
|
||||
OutputPrintable {
|
||||
Ok(OutputPrintable {
|
||||
output_type,
|
||||
commit: output.commit,
|
||||
spent,
|
||||
|
@ -295,7 +299,7 @@ impl OutputPrintable {
|
|||
block_height,
|
||||
merkle_proof,
|
||||
mmr_index: output_pos,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn commit(&self) -> Result<pedersen::Commitment, ser::Error> {
|
||||
|
@ -303,12 +307,13 @@ impl OutputPrintable {
|
|||
}
|
||||
|
||||
pub fn range_proof(&self) -> Result<pedersen::RangeProof, ser::Error> {
|
||||
let proof_str = self
|
||||
.proof
|
||||
.clone()
|
||||
.ok_or_else(|| ser::Error::HexError(format!("output range_proof missing")))
|
||||
.unwrap();
|
||||
let p_vec = util::from_hex(proof_str).unwrap();
|
||||
let proof_str = match self.proof.clone() {
|
||||
Some(p) => p,
|
||||
None => return Err(ser::Error::HexError(format!("output range_proof missing"))),
|
||||
};
|
||||
|
||||
let p_vec = util::from_hex(proof_str)
|
||||
.map_err(|_| ser::Error::HexError(format!("invalud output range_proof")))?;
|
||||
let mut p_bytes = [0; util::secp::constants::MAX_PROOF_SIZE];
|
||||
for i in 0..p_bytes.len() {
|
||||
p_bytes[i] = p_vec[i];
|
||||
|
@ -428,6 +433,15 @@ impl<'de> serde::de::Deserialize<'de> for OutputPrintable {
|
|||
}
|
||||
}
|
||||
|
||||
if output_type.is_none()
|
||||
|| commit.is_none()
|
||||
|| spent.is_none()
|
||||
|| proof_hash.is_none()
|
||||
|| mmr_index.is_none()
|
||||
{
|
||||
return Err(serde::de::Error::custom("invalid output"));
|
||||
}
|
||||
|
||||
Ok(OutputPrintable {
|
||||
output_type: output_type.unwrap(),
|
||||
commit: commit.unwrap(),
|
||||
|
@ -570,7 +584,7 @@ impl BlockPrintable {
|
|||
block: &core::Block,
|
||||
chain: Arc<chain::Chain>,
|
||||
include_proof: bool,
|
||||
) -> BlockPrintable {
|
||||
) -> Result<BlockPrintable, chain::Error> {
|
||||
let inputs = block
|
||||
.inputs()
|
||||
.iter()
|
||||
|
@ -587,18 +601,19 @@ impl BlockPrintable {
|
|||
include_proof,
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let kernels = block
|
||||
.kernels()
|
||||
.iter()
|
||||
.map(|kernel| TxKernelPrintable::from_txkernel(kernel))
|
||||
.collect();
|
||||
BlockPrintable {
|
||||
Ok(BlockPrintable {
|
||||
header: BlockHeaderPrintable::from_header(&block.header),
|
||||
inputs: inputs,
|
||||
outputs: outputs,
|
||||
kernels: kernels,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,24 +635,24 @@ impl CompactBlockPrintable {
|
|||
pub fn from_compact_block(
|
||||
cb: &core::CompactBlock,
|
||||
chain: Arc<chain::Chain>,
|
||||
) -> CompactBlockPrintable {
|
||||
let block = chain.get_block(&cb.hash()).unwrap();
|
||||
) -> Result<CompactBlockPrintable, chain::Error> {
|
||||
let block = chain.get_block(&cb.hash())?;
|
||||
let out_full = cb
|
||||
.out_full()
|
||||
.iter()
|
||||
.map(|x| OutputPrintable::from_output(x, chain.clone(), Some(&block.header), false))
|
||||
.collect();
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let kern_full = cb
|
||||
.kern_full()
|
||||
.iter()
|
||||
.map(|x| TxKernelPrintable::from_txkernel(x))
|
||||
.collect();
|
||||
CompactBlockPrintable {
|
||||
Ok(CompactBlockPrintable {
|
||||
header: BlockHeaderPrintable::from_header(&cb.header),
|
||||
out_full,
|
||||
kern_full,
|
||||
kern_ids: cb.kern_ids().iter().map(|x| x.to_hex()).collect(),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -180,3 +180,12 @@ macro_rules! parse_param_no_err(
|
|||
}
|
||||
}
|
||||
));
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! w_fut(
|
||||
($p: expr) =>(
|
||||
match w($p) {
|
||||
Ok(p) => p,
|
||||
Err(_) => return response(StatusCode::INTERNAL_SERVER_ERROR, "weak reference upgrade failed" ),
|
||||
}
|
||||
));
|
||||
|
|
|
@ -2,7 +2,7 @@ use grin_api as api;
|
|||
use grin_util as util;
|
||||
|
||||
use crate::api::*;
|
||||
use hyper::{Body, Request};
|
||||
use hyper::{Body, Request, StatusCode};
|
||||
use std::net::SocketAddr;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
|
||||
use std::sync::Arc;
|
||||
|
@ -43,7 +43,10 @@ impl Handler for CounterMiddleware {
|
|||
mut handlers: Box<dyn Iterator<Item = HandlerObj>>,
|
||||
) -> ResponseFuture {
|
||||
self.counter.fetch_add(1, Ordering::SeqCst);
|
||||
handlers.next().unwrap().call(req, handlers)
|
||||
match handlers.next() {
|
||||
Some(h) => h.call(req, handlers),
|
||||
None => return response(StatusCode::INTERNAL_SERVER_ERROR, "no handler found"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
//! invocations) as needed.
|
||||
//! Still experimental
|
||||
use crate::adapters::{FileWalletCommAdapter, HTTPWalletCommAdapter, KeybaseWalletCommAdapter};
|
||||
use crate::api::{ApiServer, BasicAuthMiddleware, Handler, ResponseFuture, Router, TLSConfig};
|
||||
use crate::api::{
|
||||
ApiServer, BasicAuthMiddleware, Handler, ResponseFuture, Router, TLSConfig, GRIN_BASIC_REALM,
|
||||
};
|
||||
use crate::core::core;
|
||||
use crate::core::core::Transaction;
|
||||
use crate::keychain::Keychain;
|
||||
|
@ -89,8 +91,8 @@ where
|
|||
if api_secret.is_some() {
|
||||
let api_basic_auth =
|
||||
"Basic ".to_string() + &to_base64(&("grin:".to_string() + &api_secret.unwrap()));
|
||||
let basic_realm = "Basic realm=GrinOwnerAPI".to_string();
|
||||
let basic_auth_middleware = Arc::new(BasicAuthMiddleware::new(api_basic_auth, basic_realm));
|
||||
let basic_auth_middleware =
|
||||
Arc::new(BasicAuthMiddleware::new(api_basic_auth, &GRIN_BASIC_REALM));
|
||||
router.add_middleware(basic_auth_middleware);
|
||||
}
|
||||
router
|
||||
|
|
|
@ -75,7 +75,7 @@ fn get_outputs_by_pmmr_index_local(
|
|||
outputs: outputs
|
||||
.2
|
||||
.iter()
|
||||
.map(|x| api::OutputPrintable::from_output(x, chain.clone(), None, true))
|
||||
.map(|x| api::OutputPrintable::from_output(x, chain.clone(), None, true).unwrap())
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue