ac6ed71abd
Also add some API tests
63 lines
2.1 KiB
Rust
63 lines
2.1 KiB
Rust
// Copyright 2018 The Grin Developers
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
use crate::chain;
|
|
use crate::core::core::{OutputFeatures, OutputIdentifier};
|
|
use crate::rest::*;
|
|
use crate::types::*;
|
|
use crate::util;
|
|
use crate::util::secp::pedersen::Commitment;
|
|
use failure::ResultExt;
|
|
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()
|
|
}
|
|
|
|
/// Retrieves an output from the chain given a commit id (a tiny bit iteratively)
|
|
pub fn get_output(
|
|
chain: &Weak<chain::Chain>,
|
|
id: &str,
|
|
) -> Result<(Output, OutputIdentifier), Error> {
|
|
let c = util::from_hex(String::from(id)).context(ErrorKind::Argument(format!(
|
|
"Not a valid commitment: {}",
|
|
id
|
|
)))?;
|
|
let commit = Commitment::from_vec(c);
|
|
|
|
// We need the features here to be able to generate the necessary hash
|
|
// to compare against the hash in the output MMR.
|
|
// For now we can just try both (but this probably needs to be part of the api
|
|
// params)
|
|
let outputs = [
|
|
OutputIdentifier::new(OutputFeatures::Plain, &commit),
|
|
OutputIdentifier::new(OutputFeatures::Coinbase, &commit),
|
|
];
|
|
|
|
for x in outputs.iter().filter(|x| w(chain).is_unspent(x).is_ok()) {
|
|
let block_height = w(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);
|
|
return Ok((Output::new(&commit, block_height, output_pos), x.clone()));
|
|
}
|
|
Err(ErrorKind::NotFound)?
|
|
}
|