review fixes
Some checks failed
Deny / audit (push) Has been cancelled

This commit is contained in:
hinto.janai 2024-12-20 20:50:03 -05:00
parent ecf5d66a91
commit 85ebc679b2
No known key found for this signature in database
GPG key ID: D47CE05FA175A499
16 changed files with 132 additions and 84 deletions

View file

@ -1,4 +1,8 @@
//! RPC request handler functions (binary endpoints). //! RPC request handler functions (binary endpoints).
//!
//! TODO:
//! Some handlers have `todo!()`s for other Cuprate internals that must be completed, see:
//! <https://github.com/Cuprate/cuprate/pull/355>
use std::num::NonZero; use std::num::NonZero;

View file

@ -170,7 +170,7 @@ pub(super) async fn top_height(state: &mut CupratedRpcHandler) -> Result<(u64, [
Ok((height, hash)) Ok((height, hash))
} }
/// TODO /// TODO: impl bootstrap
pub const fn response_base(is_bootstrap: bool) -> ResponseBase { pub const fn response_base(is_bootstrap: bool) -> ResponseBase {
if is_bootstrap { if is_bootstrap {
ResponseBase::OK_UNTRUSTED ResponseBase::OK_UNTRUSTED
@ -179,7 +179,7 @@ pub const fn response_base(is_bootstrap: bool) -> ResponseBase {
} }
} }
/// TODO /// TODO: impl bootstrap
pub const fn access_response_base(is_bootstrap: bool) -> AccessResponseBase { pub const fn access_response_base(is_bootstrap: bool) -> AccessResponseBase {
if is_bootstrap { if is_bootstrap {
AccessResponseBase::OK_UNTRUSTED AccessResponseBase::OK_UNTRUSTED

View file

@ -1,8 +1,8 @@
//! RPC request handler functions (JSON-RPC). //! RPC request handler functions (JSON-RPC).
//! //!
//! TODO: //! TODO:
//! Many handlers have `todo!()`s for other Cuprate internals that must be completed, see: //! Some handlers have `todo!()`s for other Cuprate internals that must be completed, see:
//! <https://github.com/Cuprate/cuprate/pull/308> //! <https://github.com/Cuprate/cuprate/pull/355>
use std::{ use std::{
net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4}, net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4},
@ -147,23 +147,26 @@ async fn get_block_template(
return Err(anyhow!("Too big extra_nonce size")); return Err(anyhow!("Too big extra_nonce size"));
} }
// cryptonote::address_parse_info info; // TODO: this is hardcoded for the current address scheme + mainnet,
// create/use a more well-defined wallet lib.
let parse_wallet_address = || {
if request.wallet_address.len() == 95 {
Ok(())
} else {
Err(())
}
};
let is_correct_address_type = || !request.wallet_address.starts_with("4");
if request.wallet_address.is_empty() if parse_wallet_address().is_err() {
|| todo!(
"!cryptonote::get_account_address_from_str(info, nettype(), request.wallet_address))"
)
{
return Err(anyhow!("Failed to parse wallet address")); return Err(anyhow!("Failed to parse wallet address"));
} }
if todo!("info.is_subaddress") { if is_correct_address_type() {
return Err(anyhow!("Mining to subaddress is not supported yet")); return Err(anyhow!("Incorrect address type"));
} }
let blob_reserve = hex::decode(request.extra_nonce)?; let prev_block = request.prev_block.try_into().unwrap_or([0; 32]);
let prev_block: [u8; 32] = request.prev_block.try_into()?;
let extra_nonce = hex::decode(request.extra_nonce)?;
let BlockTemplate { let BlockTemplate {
block, block,
@ -178,14 +181,13 @@ async fn get_block_template(
&mut state.blockchain_manager, &mut state.blockchain_manager,
prev_block, prev_block,
request.wallet_address, request.wallet_address,
extra_nonce, request.extra_nonce.0,
) )
.await?; .await?;
let blockhashing_blob = HexVec(block.serialize_pow_hash()); let blockhashing_blob = HexVec(block.serialize_pow_hash());
let blocktemplate_blob = HexVec(block.serialize()); let blocktemplate_blob = HexVec(block.serialize());
let (difficulty, difficulty_top64) = split_u128_into_low_high_bits(difficulty); let (difficulty, difficulty_top64) = split_u128_into_low_high_bits(difficulty);
// let next_seed_hash = Hex(next_seed_hash);
let next_seed_hash = HexVec::empty_if_zeroed(next_seed_hash); let next_seed_hash = HexVec::empty_if_zeroed(next_seed_hash);
let prev_hash = Hex(block.header.previous); let prev_hash = Hex(block.header.previous);
let seed_hash = Hex(seed_hash); let seed_hash = Hex(seed_hash);
@ -242,7 +244,7 @@ async fn submit_block(
) -> Result<SubmitBlockResponse, Error> { ) -> Result<SubmitBlockResponse, Error> {
// Parse hex into block. // Parse hex into block.
let [blob] = request.block_blob; let [blob] = request.block_blob;
let block = Block::read(&mut blob.0.as_slice())?; let block = Block::read(&mut blob.as_slice())?;
let block_id = Hex(block.hash()); let block_id = Hex(block.hash());
// Attempt to relay the block. // Attempt to relay the block.
@ -562,8 +564,8 @@ async fn get_info(
address_book::peerlist_size::<ClearNet>(&mut DummyAddressBook).await? address_book::peerlist_size::<ClearNet>(&mut DummyAddressBook).await?
}; };
let wide_cumulative_difficulty = format!("{cumulative_difficulty:#x}"); let wide_cumulative_difficulty = cumulative_difficulty.hex_prefix();
let wide_difficulty = format!("{:#x}", c.next_difficulty); let wide_difficulty = c.next_difficulty.hex_prefix();
Ok(GetInfoResponse { Ok(GetInfoResponse {
base: helper::access_response_base(false), base: helper::access_response_base(false),
@ -799,8 +801,8 @@ async fn get_coinbase_tx_sum(
.await?; .await?;
// Formats `u128` as hexadecimal strings. // Formats `u128` as hexadecimal strings.
let wide_emission_amount = format!("{fee_amount:#x}"); let wide_emission_amount = fee_amount.hex_prefix();
let wide_fee_amount = format!("{emission_amount:#x}"); let wide_fee_amount = emission_amount.hex_prefix();
Ok(GetCoinbaseTxSumResponse { Ok(GetCoinbaseTxSumResponse {
base: helper::access_response_base(false), base: helper::access_response_base(false),
@ -979,7 +981,7 @@ async fn get_miner_data(
let height = usize_to_u64(c.chain_height); let height = usize_to_u64(c.chain_height);
let prev_id = Hex(c.top_hash); let prev_id = Hex(c.top_hash);
let seed_hash = Hex(c.top_hash); let seed_hash = Hex(c.top_hash);
let difficulty = format!("{:#x}", c.next_difficulty); let difficulty = c.next_difficulty.hex_prefix();
let median_weight = usize_to_u64(c.median_weight_for_block_reward); let median_weight = usize_to_u64(c.median_weight_for_block_reward);
let already_generated_coins = c.already_generated_coins; let already_generated_coins = c.already_generated_coins;
let tx_backlog = txpool::backlog(&mut state.txpool_read) let tx_backlog = txpool::backlog(&mut state.txpool_read)
@ -1028,7 +1030,7 @@ async fn calc_pow(
request: CalcPowRequest, request: CalcPowRequest,
) -> Result<CalcPowResponse, Error> { ) -> Result<CalcPowResponse, Error> {
let hardfork = HardFork::from_version(request.major_version)?; let hardfork = HardFork::from_version(request.major_version)?;
let block = Block::read(&mut request.block_blob.0.as_slice())?; let block = Block::read(&mut request.block_blob.as_slice())?;
let seed_hash = request.seed_hash.0; let seed_hash = request.seed_hash.0;
// let block_weight = todo!(); // let block_weight = todo!();
@ -1219,7 +1221,7 @@ fn add_aux_pow_inner(
let merkle_root = tree_hash(aux_pow_raw.as_ref()); let merkle_root = tree_hash(aux_pow_raw.as_ref());
let merkle_tree_depth = encode_mm_depth(len, nonce); let merkle_tree_depth = encode_mm_depth(len, nonce);
let block_template = Block::read(&mut request.blocktemplate_blob.0.as_slice())?; let block_template = Block::read(&mut request.blocktemplate_blob.as_slice())?;
fn remove_field_from_tx_extra() -> Result<(), ()> { fn remove_field_from_tx_extra() -> Result<(), ()> {
todo!("https://github.com/monero-project/monero/blob/master/src/cryptonote_basic/cryptonote_format_utils.cpp#L767") todo!("https://github.com/monero-project/monero/blob/master/src/cryptonote_basic/cryptonote_format_utils.cpp#L767")

View file

@ -1,4 +1,8 @@
//! RPC request handler functions (other JSON endpoints). //! RPC request handler functions (other JSON endpoints).
//!
//! TODO:
//! Some handlers have `todo!()`s for other Cuprate internals that must be completed, see:
//! <https://github.com/Cuprate/cuprate/pull/355>
use std::{ use std::{
borrow::Cow, borrow::Cow,
@ -6,6 +10,7 @@ use std::{
}; };
use anyhow::{anyhow, Error}; use anyhow::{anyhow, Error};
use monero_serai::transaction::{Input, Timelock, Transaction};
use cuprate_constants::rpc::{ use cuprate_constants::rpc::{
MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT, RESTRICTED_SPENT_KEY_IMAGES_COUNT, MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT, RESTRICTED_SPENT_KEY_IMAGES_COUNT,
@ -40,7 +45,6 @@ use cuprate_types::{
rpc::{KeyImageSpentStatus, PoolInfo, PoolTxInfo, PublicNode}, rpc::{KeyImageSpentStatus, PoolInfo, PoolTxInfo, PublicNode},
TxInPool, TxRelayChecks, TxInPool, TxRelayChecks,
}; };
use monero_serai::transaction::{Input, Timelock, Transaction};
use crate::{ use crate::{
rpc::{ rpc::{
@ -173,7 +177,7 @@ async fn get_transactions(
txs_as_hex.push(as_hex.clone()); txs_as_hex.push(as_hex.clone());
let as_json = if request.decode_as_json { let as_json = if request.decode_as_json {
let tx = Transaction::read(&mut as_hex.0.as_slice())?; let tx = Transaction::read(&mut as_hex.as_slice())?;
let json_type = cuprate_types::json::tx::Transaction::from(tx); let json_type = cuprate_types::json::tx::Transaction::from(tx);
let json = serde_json::to_string(&json_type).unwrap(); let json = serde_json::to_string(&json_type).unwrap();
txs_as_json.push(json.clone()); txs_as_json.push(json.clone());
@ -351,7 +355,7 @@ async fn send_raw_transaction(
tx_extra_too_big: false, tx_extra_too_big: false,
}; };
let tx = Transaction::read(&mut request.tx_as_hex.0.as_slice())?; let tx = Transaction::read(&mut request.tx_as_hex.as_slice())?;
if request.do_sanity_checks { if request.do_sanity_checks {
/// FIXME: these checks could be defined elsewhere. /// FIXME: these checks could be defined elsewhere.

View file

@ -1,4 +1,8 @@
//! RPC handler functions that are shared between different endpoint/methods. //! RPC handler functions that are shared between different endpoint/methods.
//!
//! TODO:
//! Some handlers have `todo!()`s for other Cuprate internals that must be completed, see:
//! <https://github.com/Cuprate/cuprate/pull/355>
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},

View file

@ -3,7 +3,6 @@
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use anyhow::Error; use anyhow::Error;
use cuprate_types::BlockTemplate;
use futures::future::BoxFuture; use futures::future::BoxFuture;
use monero_serai::block::Block; use monero_serai::block::Block;
use tower::Service; use tower::Service;
@ -18,6 +17,7 @@ use cuprate_rpc_types::{
other::{OtherRequest, OtherResponse}, other::{OtherRequest, OtherResponse},
}; };
use cuprate_txpool::service::TxpoolReadHandle; use cuprate_txpool::service::TxpoolReadHandle;
use cuprate_types::BlockTemplate;
use crate::rpc::handlers; use crate::rpc::handlers;
@ -41,7 +41,7 @@ pub enum BlockchainManagerRequest {
Box<Block>, Box<Block>,
), ),
/// TODO /// Sync/flush the blockchain database to disk.
Sync, Sync,
/// Is the blockchain in the middle of syncing? /// Is the blockchain in the middle of syncing?
@ -89,14 +89,14 @@ pub enum BlockchainManagerRequest {
/// Get the next [`PruningSeed`] needed for a pruned sync. /// Get the next [`PruningSeed`] needed for a pruned sync.
NextNeededPruningSeed, NextNeededPruningSeed,
/// TODO /// Create a block template.
CreateBlockTemplate { CreateBlockTemplate {
prev_block: [u8; 32], prev_block: [u8; 32],
account_public_address: String, account_public_address: String,
extra_nonce: Vec<u8>, extra_nonce: Vec<u8>,
}, },
/// TODO /// Safely shutdown `cuprated`.
Stop, Stop,
} }
@ -140,8 +140,6 @@ pub enum BlockchainManagerResponse {
height: usize, height: usize,
}, },
// /// Response to [`BlockchainManagerRequest::Spans`].
// Spans(Vec<Span<Z::Addr>>),
/// Response to [`BlockchainManagerRequest::NextNeededPruningSeed`]. /// Response to [`BlockchainManagerRequest::NextNeededPruningSeed`].
NextNeededPruningSeed(PruningSeed), NextNeededPruningSeed(PruningSeed),

View file

@ -3,7 +3,6 @@
use std::net::SocketAddrV4; use std::net::SocketAddrV4;
use anyhow::{anyhow, Error}; use anyhow::{anyhow, Error};
use cuprate_types::rpc::Peer;
use tower::ServiceExt; use tower::ServiceExt;
use cuprate_helper::{cast::usize_to_u64, map::u32_from_ipv4}; use cuprate_helper::{cast::usize_to_u64, map::u32_from_ipv4};
@ -13,6 +12,7 @@ use cuprate_p2p_core::{
AddressBook, NetworkZone, AddressBook, NetworkZone,
}; };
use cuprate_rpc_types::misc::ConnectionInfo; use cuprate_rpc_types::misc::ConnectionInfo;
use cuprate_types::rpc::Peer;
// FIXME: use `anyhow::Error` over `tower::BoxError` in address book. // FIXME: use `anyhow::Error` over `tower::BoxError` in address book.

View file

@ -1,7 +1,6 @@
//! Functions to send [`BlockchainManagerRequest`]s. //! Functions to send [`BlockchainManagerRequest`]s.
use anyhow::Error; use anyhow::Error;
use cuprate_types::BlockTemplate;
use monero_serai::block::Block; use monero_serai::block::Block;
use tower::{Service, ServiceExt}; use tower::{Service, ServiceExt};
@ -9,6 +8,7 @@ use cuprate_helper::cast::{u64_to_usize, usize_to_u64};
use cuprate_p2p_core::{types::ConnectionId, NetworkZone}; use cuprate_p2p_core::{types::ConnectionId, NetworkZone};
use cuprate_pruning::PruningSeed; use cuprate_pruning::PruningSeed;
use cuprate_rpc_types::misc::Span; use cuprate_rpc_types::misc::Span;
use cuprate_types::BlockTemplate;
use crate::rpc::rpc_handler::{ use crate::rpc::rpc_handler::{
BlockchainManagerHandle, BlockchainManagerRequest, BlockchainManagerResponse, BlockchainManagerHandle, BlockchainManagerRequest, BlockchainManagerResponse,

View file

@ -1,6 +1,8 @@
//! Formatting. //! String formatting.
/// A type that can be represented in hexadecimal (with a `0x` prefix).
pub trait HexPrefix { pub trait HexPrefix {
/// Turn `self` into a hexadecimal string prefixed with `0x`.
fn hex_prefix(self) -> String; fn hex_prefix(self) -> String;
} }

View file

@ -111,15 +111,6 @@ impl From<HistogramEntry> for crate::misc::HistogramEntry {
} }
} }
// impl From<HardforkEntry> for crate::misc::HardforkEntry {
// fn from(x: HardforkEntry) -> Self {
// Self {
// height: x.height,
// hf_version: x.hf_version,
// }
// }
// }
impl From<ChainInfo> for crate::misc::ChainInfo { impl From<ChainInfo> for crate::misc::ChainInfo {
fn from(x: ChainInfo) -> Self { fn from(x: ChainInfo) -> Self {
Self { Self {
@ -150,18 +141,6 @@ impl From<Span<SocketAddr>> for crate::misc::Span {
} }
} }
// impl From<OutputDistributionData> for crate::misc::OutputDistributionData {
// fn from(x: OutputDistributionData) -> Self {
// todo!();
// // Self {
// // distribution: Vec<u64>,
// // start_height: u64,
// // base: u64,
// // }
// }
// }
impl From<TxInfo> for crate::misc::TxInfo { impl From<TxInfo> for crate::misc::TxInfo {
fn from(x: TxInfo) -> Self { fn from(x: TxInfo) -> Self {
Self { Self {

View file

@ -76,11 +76,11 @@ define_request_and_response! {
// 1. As an expression // 1. As an expression
// 2. As a string literal // 2. As a string literal
// //
// For example: `extra_nonce: String /* = default_string(), "default_string" */,` // For example: `extra_nonce: HexVec /* = default::<HexVec>(), "default" */,`
// //
// This is a HACK since `serde`'s default attribute only takes in // This is a HACK since `serde`'s default attribute only takes in
// string literals and macros (stringify) within attributes do not work. // string literals and macros (stringify) within attributes do not work.
extra_nonce: String = default::<String>(), "default", extra_nonce: HexVec = default::<HexVec>(), "default",
prev_block: HexVec = default::<HexVec>(), "default", prev_block: HexVec = default::<HexVec>(), "default",
// Another optional expression: // Another optional expression:
@ -958,7 +958,7 @@ mod test {
fn get_block_template_request() { fn get_block_template_request() {
test_json_request(json::GET_BLOCK_TEMPLATE_REQUEST, GetBlockTemplateRequest { test_json_request(json::GET_BLOCK_TEMPLATE_REQUEST, GetBlockTemplateRequest {
reserve_size: 60, reserve_size: 60,
extra_nonce: String::default(), extra_nonce: HexVec::default(),
prev_block: HexVec::default(), prev_block: HexVec::default(),
wallet_address: "44GBHzv6ZyQdJkjqZje6KLZ3xSyN1hBSFAnLP6EAqJtCRVzMzZmeXTC2AHKDS9aEDTRKmo6a6o9r9j86pYfhCWDkKjbtcns".into(), wallet_address: "44GBHzv6ZyQdJkjqZje6KLZ3xSyN1hBSFAnLP6EAqJtCRVzMzZmeXTC2AHKDS9aEDTRKmo6a6o9r9j86pYfhCWDkKjbtcns".into(),
}); });

View file

@ -1,4 +1,4 @@
//! TODO //! [`RequestedInfo`]
//---------------------------------------------------------------------------------------------------- Use //---------------------------------------------------------------------------------------------------- Use
#[cfg(feature = "serde")] #[cfg(feature = "serde")]

View file

@ -19,6 +19,10 @@ use crate::{
//---------------------------------------------------------------------------------------------------- TxpoolReadRequest //---------------------------------------------------------------------------------------------------- TxpoolReadRequest
/// The transaction pool [`tower::Service`] read request type. /// The transaction pool [`tower::Service`] read request type.
///
/// ### `include_sensitive_txs`
/// This field exists in many requests.
/// If this is [`true`], the request will include private (local) transactions in the response.
#[derive(Clone)] #[derive(Clone)]
pub enum TxpoolReadRequest { pub enum TxpoolReadRequest {
/// Get the blob (raw bytes) of a transaction with the given hash. /// Get the blob (raw bytes) of a transaction with the given hash.
@ -39,42 +43,38 @@ pub enum TxpoolReadRequest {
Backlog, Backlog,
/// Get the number of transactions in the pool. /// Get the number of transactions in the pool.
Size { Size { include_sensitive_txs: bool },
/// If this is [`true`], the size returned will
/// include private transactions in the pool.
include_sensitive_txs: bool,
},
/// Get general information on the txpool. /// Get general information on the txpool.
PoolInfo { PoolInfo {
/// If this is [`true`], the size returned will
/// include private transactions in the pool.
include_sensitive_txs: bool, include_sensitive_txs: bool,
/// TODO /// The maximum amount of transactions to retrieve.
max_tx_count: usize, max_tx_count: usize,
/// TODO /// Fetch transactions that start from this time.
///
/// [`None`] means all transactions.
start_time: Option<NonZero<usize>>, start_time: Option<NonZero<usize>>,
}, },
/// TODO /// Get transactions by their hashes.
TxsByHash { TxsByHash {
tx_hashes: Vec<[u8; 32]>, tx_hashes: Vec<[u8; 32]>,
include_sensitive_txs: bool, include_sensitive_txs: bool,
}, },
/// TODO /// Check if certain key images exist in the txpool.
KeyImagesSpent { KeyImagesSpent {
key_images: Vec<[u8; 32]>, key_images: Vec<[u8; 32]>,
include_sensitive_txs: bool, include_sensitive_txs: bool,
}, },
/// TODO /// Get txpool info.
Pool { include_sensitive_txs: bool }, Pool { include_sensitive_txs: bool },
/// TODO /// Get txpool stats.
PoolStats { include_sensitive_txs: bool }, PoolStats { include_sensitive_txs: bool },
/// TODO /// Get the hashes of all transaction in the pool.
AllHashes { include_sensitive_txs: bool }, AllHashes { include_sensitive_txs: bool },
} }

View file

@ -3,6 +3,11 @@
//! This module provides transparent wrapper types for //! This module provides transparent wrapper types for
//! arrays that (de)serialize from hexadecimal input/output. //! arrays that (de)serialize from hexadecimal input/output.
use std::{
borrow::Borrow,
ops::{Deref, DerefMut},
};
use hex::{FromHex, FromHexError}; use hex::{FromHex, FromHexError};
use serde::{Deserialize, Deserializer, Serialize}; use serde::{Deserialize, Deserializer, Serialize};
@ -74,6 +79,31 @@ impl<const N: usize> Default for Hex<N> {
} }
} }
impl<const N: usize> Deref for Hex<N> {
type Target = [u8; N];
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<const N: usize> DerefMut for Hex<N> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<const N: usize> Borrow<[u8; N]> for Hex<N> {
fn borrow(&self) -> &[u8; N] {
&self.0
}
}
impl<const N: usize> AsRef<[u8; N]> for Hex<N> {
fn as_ref(&self) -> &[u8; N] {
&self.0
}
}
impl<const N: usize> From<Hex<N>> for [u8; N] { impl<const N: usize> From<Hex<N>> for [u8; N] {
fn from(hex: Hex<N>) -> Self { fn from(hex: Hex<N>) -> Self {
hex.0 hex.0

View file

@ -3,6 +3,11 @@
//! This module provides transparent wrapper types for //! This module provides transparent wrapper types for
//! arrays that (de)serialize from hexadecimal input/output. //! arrays that (de)serialize from hexadecimal input/output.
use std::{
borrow::Borrow,
ops::{Deref, DerefMut},
};
use hex::FromHexError; use hex::FromHexError;
use serde::{Deserialize, Deserializer, Serialize}; use serde::{Deserialize, Deserializer, Serialize};
@ -42,11 +47,6 @@ impl HexVec {
Self(Vec::new()) Self(Vec::new())
} }
/// [`Vec::is_empty`].
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// Returns an empty [`Self`] if `array` is all `0`s. /// Returns an empty [`Self`] if `array` is all `0`s.
/// ///
/// ```rust /// ```rust
@ -73,6 +73,31 @@ impl<'de> Deserialize<'de> for HexVec {
} }
} }
impl Deref for HexVec {
type Target = Vec<u8>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for HexVec {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl Borrow<Vec<u8>> for HexVec {
fn borrow(&self) -> &Vec<u8> {
&self.0
}
}
impl AsRef<Vec<u8>> for HexVec {
fn as_ref(&self) -> &Vec<u8> {
&self.0
}
}
impl From<HexVec> for Vec<u8> { impl From<HexVec> for Vec<u8> {
fn from(hex: HexVec) -> Self { fn from(hex: HexVec) -> Self {
hex.0 hex.0

View file

@ -175,13 +175,13 @@ pub enum BlockchainReadRequest {
/// Get the amount of alternative chains that exist. /// Get the amount of alternative chains that exist.
AltChainCount, AltChainCount,
/// TODO /// Get transaction blobs by their hashes.
Transactions { tx_hashes: HashSet<[u8; 32]> }, Transactions { tx_hashes: HashSet<[u8; 32]> },
/// TODO /// Get the total amount of RCT outputs in the blockchain.
TotalRctOutputs, TotalRctOutputs,
/// TODO /// Get the output indexes of a transaction.
TxOutputIndexes { tx_hash: [u8; 32] }, TxOutputIndexes { tx_hash: [u8; 32] },
} }