mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-12-22 19:49:33 +00:00
finish other draft
This commit is contained in:
parent
805f475083
commit
0b3ee2d1d1
5 changed files with 122 additions and 30 deletions
|
@ -37,10 +37,10 @@ use cuprate_rpc_types::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use cuprate_types::{
|
use cuprate_types::{
|
||||||
rpc::{KeyImageSpentStatus, OutKey, PoolInfo, PoolTxInfo},
|
rpc::{KeyImageSpentStatus, OutKey, PoolInfo, PoolTxInfo, PublicNode},
|
||||||
TxInPool, TxRelayChecks,
|
TxInPool, TxRelayChecks,
|
||||||
};
|
};
|
||||||
use monero_serai::transaction::{Input, Transaction};
|
use monero_serai::transaction::{Input, Timelock, Transaction};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
constants::UNSUPPORTED_RPC_CALL,
|
constants::UNSUPPORTED_RPC_CALL,
|
||||||
|
@ -49,6 +49,7 @@ use crate::{
|
||||||
request::{blockchain, blockchain_context, blockchain_manager, txpool},
|
request::{blockchain, blockchain_context, blockchain_manager, txpool},
|
||||||
CupratedRpcHandler,
|
CupratedRpcHandler,
|
||||||
},
|
},
|
||||||
|
statics::START_INSTANT_UNIX,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::request::address_book;
|
use super::request::address_book;
|
||||||
|
@ -541,9 +542,12 @@ async fn get_limit(
|
||||||
mut state: CupratedRpcHandler,
|
mut state: CupratedRpcHandler,
|
||||||
_: GetLimitRequest,
|
_: GetLimitRequest,
|
||||||
) -> Result<GetLimitResponse, Error> {
|
) -> Result<GetLimitResponse, Error> {
|
||||||
|
todo!("waiting on p2p service");
|
||||||
|
|
||||||
Ok(GetLimitResponse {
|
Ok(GetLimitResponse {
|
||||||
base: helper::response_base(false),
|
base: helper::response_base(false),
|
||||||
..todo!()
|
limit_down: todo!(),
|
||||||
|
limit_up: todo!(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,9 +556,12 @@ async fn set_limit(
|
||||||
mut state: CupratedRpcHandler,
|
mut state: CupratedRpcHandler,
|
||||||
request: SetLimitRequest,
|
request: SetLimitRequest,
|
||||||
) -> Result<SetLimitResponse, Error> {
|
) -> Result<SetLimitResponse, Error> {
|
||||||
|
todo!("waiting on p2p service");
|
||||||
|
|
||||||
Ok(SetLimitResponse {
|
Ok(SetLimitResponse {
|
||||||
base: helper::response_base(false),
|
base: helper::response_base(false),
|
||||||
..todo!()
|
limit_down: todo!(),
|
||||||
|
limit_up: todo!(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,9 +570,11 @@ async fn out_peers(
|
||||||
mut state: CupratedRpcHandler,
|
mut state: CupratedRpcHandler,
|
||||||
request: OutPeersRequest,
|
request: OutPeersRequest,
|
||||||
) -> Result<OutPeersResponse, Error> {
|
) -> Result<OutPeersResponse, Error> {
|
||||||
|
todo!("waiting on p2p service");
|
||||||
|
|
||||||
Ok(OutPeersResponse {
|
Ok(OutPeersResponse {
|
||||||
base: helper::response_base(false),
|
base: helper::response_base(false),
|
||||||
..todo!()
|
out_peers: todo!(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,9 +583,11 @@ async fn in_peers(
|
||||||
mut state: CupratedRpcHandler,
|
mut state: CupratedRpcHandler,
|
||||||
request: InPeersRequest,
|
request: InPeersRequest,
|
||||||
) -> Result<InPeersResponse, Error> {
|
) -> Result<InPeersResponse, Error> {
|
||||||
|
todo!("waiting on p2p service");
|
||||||
|
|
||||||
Ok(InPeersResponse {
|
Ok(InPeersResponse {
|
||||||
base: helper::response_base(false),
|
base: helper::response_base(false),
|
||||||
..todo!()
|
in_peers: todo!(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,9 +596,15 @@ async fn get_net_stats(
|
||||||
mut state: CupratedRpcHandler,
|
mut state: CupratedRpcHandler,
|
||||||
_: GetNetStatsRequest,
|
_: GetNetStatsRequest,
|
||||||
) -> Result<GetNetStatsResponse, Error> {
|
) -> Result<GetNetStatsResponse, Error> {
|
||||||
|
todo!("waiting on p2p service");
|
||||||
|
|
||||||
Ok(GetNetStatsResponse {
|
Ok(GetNetStatsResponse {
|
||||||
base: helper::response_base(false),
|
base: helper::response_base(false),
|
||||||
..todo!()
|
start_time: *START_INSTANT_UNIX,
|
||||||
|
total_packets_in: todo!(),
|
||||||
|
total_bytes_in: todo!(),
|
||||||
|
total_packets_out: todo!(),
|
||||||
|
total_bytes_out: todo!(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -600,32 +617,39 @@ async fn get_outs(
|
||||||
return Err(anyhow!("Too many outs requested"));
|
return Err(anyhow!("Too many outs requested"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut outputs = HashMap::<u64, HashSet<u64>>::with_capacity(request.outputs.len());
|
let outputs = {
|
||||||
for out in request.outputs {
|
let mut outputs = HashMap::<u64, HashSet<u64>>::with_capacity(request.outputs.len());
|
||||||
|
|
||||||
|
for out in request.outputs {
|
||||||
|
outputs
|
||||||
|
.entry(out.amount)
|
||||||
|
.and_modify(|set| {
|
||||||
|
set.insert(out.index);
|
||||||
|
})
|
||||||
|
.or_insert_with(|| HashSet::from([out.index]));
|
||||||
|
}
|
||||||
|
|
||||||
outputs
|
outputs
|
||||||
.entry(out.amount)
|
};
|
||||||
.and_modify(|set| {
|
|
||||||
set.insert(out.index);
|
|
||||||
})
|
|
||||||
.or_insert_with(|| HashSet::from([out.index]));
|
|
||||||
}
|
|
||||||
|
|
||||||
let outs = blockchain::outputs(&mut state.blockchain_read, outputs)
|
let outs = blockchain::outputs(&mut state.blockchain_read, outputs)
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|(amount, index_map)| {
|
.flat_map(|(amount, index_map)| {
|
||||||
index_map.into_iter().map(|(index, out)| OutKey {
|
index_map.into_iter().map(|(index, out)| OutKey {
|
||||||
key: todo!(),
|
key: out.key.map_or(Hex([0; 32]), |e| Hex(e.compress().0)),
|
||||||
mask: todo!(),
|
mask: Hex(out.commitment.compress().0),
|
||||||
unlocked: todo!(),
|
unlocked: matches!(out.time_lock, Timelock::None),
|
||||||
height: usize_to_u64(out.height),
|
height: usize_to_u64(out.height),
|
||||||
txid: todo!(),
|
txid: if request.get_txid {
|
||||||
|
hex::encode(out.txid)
|
||||||
|
} else {
|
||||||
|
String::new()
|
||||||
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<Vec<OutKey>>();
|
.collect::<Vec<OutKey>>();
|
||||||
|
|
||||||
// TODO: check txpool
|
|
||||||
|
|
||||||
Ok(GetOutsResponse {
|
Ok(GetOutsResponse {
|
||||||
base: helper::response_base(false),
|
base: helper::response_base(false),
|
||||||
outs,
|
outs,
|
||||||
|
@ -651,9 +675,20 @@ async fn get_transaction_pool_hashes(
|
||||||
mut state: CupratedRpcHandler,
|
mut state: CupratedRpcHandler,
|
||||||
_: GetTransactionPoolHashesRequest,
|
_: GetTransactionPoolHashesRequest,
|
||||||
) -> Result<GetTransactionPoolHashesResponse, Error> {
|
) -> Result<GetTransactionPoolHashesResponse, Error> {
|
||||||
|
let include_sensitive_txs = !state.is_restricted();
|
||||||
|
|
||||||
|
// FIXME: this request is a bit overkill, we only need the hashes.
|
||||||
|
// We could create a separate request for this.
|
||||||
|
let tx_hashes = txpool::pool(&mut state.txpool_read, include_sensitive_txs)
|
||||||
|
.await?
|
||||||
|
.0
|
||||||
|
.into_iter()
|
||||||
|
.map(|tx| tx.id_hash)
|
||||||
|
.collect();
|
||||||
|
|
||||||
Ok(GetTransactionPoolHashesResponse {
|
Ok(GetTransactionPoolHashesResponse {
|
||||||
base: helper::response_base(false),
|
base: helper::response_base(false),
|
||||||
..todo!()
|
tx_hashes,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,9 +697,37 @@ async fn get_public_nodes(
|
||||||
mut state: CupratedRpcHandler,
|
mut state: CupratedRpcHandler,
|
||||||
request: GetPublicNodesRequest,
|
request: GetPublicNodesRequest,
|
||||||
) -> Result<GetPublicNodesResponse, Error> {
|
) -> Result<GetPublicNodesResponse, Error> {
|
||||||
|
let (white, gray) = address_book::peerlist::<ClearNet>(&mut DummyAddressBook).await?;
|
||||||
|
|
||||||
|
fn map(peers: Vec<cuprate_types::rpc::Peer>) -> Vec<PublicNode> {
|
||||||
|
peers
|
||||||
|
.into_iter()
|
||||||
|
.map(|peer| {
|
||||||
|
let cuprate_types::rpc::Peer {
|
||||||
|
host,
|
||||||
|
rpc_port,
|
||||||
|
rpc_credits_per_hash,
|
||||||
|
last_seen,
|
||||||
|
..
|
||||||
|
} = peer;
|
||||||
|
|
||||||
|
PublicNode {
|
||||||
|
host,
|
||||||
|
rpc_port,
|
||||||
|
rpc_credits_per_hash,
|
||||||
|
last_seen,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
let white = map(white);
|
||||||
|
let gray = map(gray);
|
||||||
|
|
||||||
Ok(GetPublicNodesResponse {
|
Ok(GetPublicNodesResponse {
|
||||||
base: helper::response_base(false),
|
base: helper::response_base(false),
|
||||||
..todo!()
|
white,
|
||||||
|
gray,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,7 @@ macro_rules! test_verify_valid_v2_tx {
|
||||||
key: CompressedEdwardsY::from_slice(&hex_literal::hex!($ring_member))
|
key: CompressedEdwardsY::from_slice(&hex_literal::hex!($ring_member))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.decompress(),
|
.decompress(),
|
||||||
|
txid: [0; 32],
|
||||||
}),)+)+
|
}),)+)+
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -107,6 +108,7 @@ macro_rules! test_verify_valid_v2_tx {
|
||||||
key: CompressedEdwardsY::from_slice(&hex_literal::hex!($ring_member))
|
key: CompressedEdwardsY::from_slice(&hex_literal::hex!($ring_member))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.decompress(),
|
.decompress(),
|
||||||
|
txid: [0; 32],
|
||||||
}),)+)+
|
}),)+)+
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,13 @@ use monero_serai::transaction::Timelock;
|
||||||
use cuprate_database::{
|
use cuprate_database::{
|
||||||
DbResult, RuntimeError, {DatabaseRo, DatabaseRw},
|
DbResult, RuntimeError, {DatabaseRo, DatabaseRw},
|
||||||
};
|
};
|
||||||
use cuprate_helper::crypto::compute_zero_commitment;
|
use cuprate_helper::{cast::u32_to_usize, crypto::compute_zero_commitment};
|
||||||
use cuprate_helper::map::u64_to_timelock;
|
use cuprate_helper::{cast::u64_to_usize, map::u64_to_timelock};
|
||||||
use cuprate_types::OutputOnChain;
|
use cuprate_types::OutputOnChain;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ops::macros::{doc_add_block_inner_invariant, doc_error},
|
ops::macros::{doc_add_block_inner_invariant, doc_error},
|
||||||
tables::{Outputs, RctOutputs, Tables, TablesMut, TxUnlockTime},
|
tables::{BlockTxsHashes, Outputs, RctOutputs, Tables, TablesMut, TxUnlockTime},
|
||||||
types::{Amount, AmountIndex, Output, OutputFlags, PreRctOutputId, RctOutput},
|
types::{Amount, AmountIndex, Output, OutputFlags, PreRctOutputId, RctOutput},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -153,6 +153,7 @@ pub fn output_to_output_on_chain(
|
||||||
output: &Output,
|
output: &Output,
|
||||||
amount: Amount,
|
amount: Amount,
|
||||||
table_tx_unlock_time: &impl DatabaseRo<TxUnlockTime>,
|
table_tx_unlock_time: &impl DatabaseRo<TxUnlockTime>,
|
||||||
|
table_block_txs_hashes: &impl DatabaseRo<BlockTxsHashes>,
|
||||||
) -> DbResult<OutputOnChain> {
|
) -> DbResult<OutputOnChain> {
|
||||||
let commitment = compute_zero_commitment(amount);
|
let commitment = compute_zero_commitment(amount);
|
||||||
|
|
||||||
|
@ -169,11 +170,18 @@ pub fn output_to_output_on_chain(
|
||||||
.map(|y| y.decompress())
|
.map(|y| y.decompress())
|
||||||
.unwrap_or(None);
|
.unwrap_or(None);
|
||||||
|
|
||||||
|
let txid = {
|
||||||
|
let height = u32_to_usize(output.height);
|
||||||
|
let tx_idx = u64_to_usize(output.tx_idx);
|
||||||
|
table_block_txs_hashes.get(&height)?[tx_idx]
|
||||||
|
};
|
||||||
|
|
||||||
Ok(OutputOnChain {
|
Ok(OutputOnChain {
|
||||||
height: output.height as usize,
|
height: output.height as usize,
|
||||||
time_lock,
|
time_lock,
|
||||||
key,
|
key,
|
||||||
commitment,
|
commitment,
|
||||||
|
txid,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,6 +197,7 @@ pub fn output_to_output_on_chain(
|
||||||
pub fn rct_output_to_output_on_chain(
|
pub fn rct_output_to_output_on_chain(
|
||||||
rct_output: &RctOutput,
|
rct_output: &RctOutput,
|
||||||
table_tx_unlock_time: &impl DatabaseRo<TxUnlockTime>,
|
table_tx_unlock_time: &impl DatabaseRo<TxUnlockTime>,
|
||||||
|
table_block_txs_hashes: &impl DatabaseRo<BlockTxsHashes>,
|
||||||
) -> DbResult<OutputOnChain> {
|
) -> DbResult<OutputOnChain> {
|
||||||
// INVARIANT: Commitments stored are valid when stored by the database.
|
// INVARIANT: Commitments stored are valid when stored by the database.
|
||||||
let commitment = CompressedEdwardsY::from_slice(&rct_output.commitment)
|
let commitment = CompressedEdwardsY::from_slice(&rct_output.commitment)
|
||||||
|
@ -209,11 +218,18 @@ pub fn rct_output_to_output_on_chain(
|
||||||
.map(|y| y.decompress())
|
.map(|y| y.decompress())
|
||||||
.unwrap_or(None);
|
.unwrap_or(None);
|
||||||
|
|
||||||
|
let txid = {
|
||||||
|
let height = u32_to_usize(rct_output.height);
|
||||||
|
let tx_idx = u64_to_usize(rct_output.tx_idx);
|
||||||
|
table_block_txs_hashes.get(&height)?[tx_idx]
|
||||||
|
};
|
||||||
|
|
||||||
Ok(OutputOnChain {
|
Ok(OutputOnChain {
|
||||||
height: rct_output.height as usize,
|
height: rct_output.height as usize,
|
||||||
time_lock,
|
time_lock,
|
||||||
key,
|
key,
|
||||||
commitment,
|
commitment,
|
||||||
|
txid,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,14 +241,22 @@ pub fn id_to_output_on_chain(id: &PreRctOutputId, tables: &impl Tables) -> DbRes
|
||||||
// v2 transactions.
|
// v2 transactions.
|
||||||
if id.amount == 0 {
|
if id.amount == 0 {
|
||||||
let rct_output = get_rct_output(&id.amount_index, tables.rct_outputs())?;
|
let rct_output = get_rct_output(&id.amount_index, tables.rct_outputs())?;
|
||||||
let output_on_chain = rct_output_to_output_on_chain(&rct_output, tables.tx_unlock_time())?;
|
let output_on_chain = rct_output_to_output_on_chain(
|
||||||
|
&rct_output,
|
||||||
|
tables.tx_unlock_time(),
|
||||||
|
tables.block_txs_hashes(),
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(output_on_chain)
|
Ok(output_on_chain)
|
||||||
} else {
|
} else {
|
||||||
// v1 transactions.
|
// v1 transactions.
|
||||||
let output = get_output(id, tables.outputs())?;
|
let output = get_output(id, tables.outputs())?;
|
||||||
let output_on_chain =
|
let output_on_chain = output_to_output_on_chain(
|
||||||
output_to_output_on_chain(&output, id.amount, tables.tx_unlock_time())?;
|
&output,
|
||||||
|
id.amount,
|
||||||
|
tables.tx_unlock_time(),
|
||||||
|
tables.block_txs_hashes(),
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(output_on_chain)
|
Ok(output_on_chain)
|
||||||
}
|
}
|
||||||
|
|
|
@ -429,7 +429,8 @@ define_struct_and_impl_epee! {
|
||||||
mask: Hex<32>,
|
mask: Hex<32>,
|
||||||
unlocked: bool,
|
unlocked: bool,
|
||||||
height: u64,
|
height: u64,
|
||||||
txid: Hex<32>,
|
// Optionally empty with `/get_outs`'s `"get_txid": false`.
|
||||||
|
txid: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc = monero_definition_link!(
|
#[doc = monero_definition_link!(
|
||||||
|
|
|
@ -145,6 +145,8 @@ pub struct OutputOnChain {
|
||||||
pub key: Option<EdwardsPoint>,
|
pub key: Option<EdwardsPoint>,
|
||||||
/// The output's commitment.
|
/// The output's commitment.
|
||||||
pub commitment: EdwardsPoint,
|
pub commitment: EdwardsPoint,
|
||||||
|
/// The transaction ID this output belongs to.
|
||||||
|
pub txid: [u8; 32],
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The inner response for a request for txs in a block.
|
/// The inner response for a request for txs in a block.
|
||||||
|
|
Loading…
Reference in a new issue