mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-12-22 19:49:33 +00:00
Compare commits
3 commits
fd84940ee6
...
e975c420d9
Author | SHA1 | Date | |
---|---|---|---|
|
e975c420d9 | ||
|
1f3b5ed127 | ||
|
46bf19861a |
3 changed files with 198 additions and 31 deletions
|
@ -8,11 +8,15 @@
|
||||||
use anyhow::{anyhow, Error};
|
use anyhow::{anyhow, Error};
|
||||||
use monero_serai::block::Block;
|
use monero_serai::block::Block;
|
||||||
|
|
||||||
|
use cuprate_consensus::{BlockChainContext, BlockChainContextService};
|
||||||
use cuprate_helper::{cast::usize_to_u64, map::split_u128_into_low_high_bits};
|
use cuprate_helper::{cast::usize_to_u64, map::split_u128_into_low_high_bits};
|
||||||
use cuprate_rpc_types::misc::{BlockHeader, KeyImageSpentStatus};
|
use cuprate_rpc_types::misc::{BlockHeader, KeyImageSpentStatus};
|
||||||
use cuprate_types::ExtendedBlockHeader;
|
use cuprate_types::ExtendedBlockHeader;
|
||||||
|
|
||||||
use crate::{rpc::request::blockchain, rpc::CupratedRpcHandler};
|
use crate::{
|
||||||
|
rpc::request::{blockchain, blockchain_context},
|
||||||
|
rpc::CupratedRpcHandler,
|
||||||
|
};
|
||||||
|
|
||||||
pub(super) fn into_block_header(
|
pub(super) fn into_block_header(
|
||||||
height: u64,
|
height: u64,
|
||||||
|
|
|
@ -13,7 +13,7 @@ use cuprate_constants::{
|
||||||
rpc::{RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE},
|
rpc::{RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE},
|
||||||
};
|
};
|
||||||
use cuprate_helper::{
|
use cuprate_helper::{
|
||||||
cast::{u64_to_usize, usize_to_u64},
|
cast::{u32_to_usize, u64_to_usize, usize_to_u64},
|
||||||
map::split_u128_into_low_high_bits,
|
map::split_u128_into_low_high_bits,
|
||||||
};
|
};
|
||||||
use cuprate_p2p_core::{client::handshaker::builder::DummyAddressBook, ClearNet, Network};
|
use cuprate_p2p_core::{client::handshaker::builder::DummyAddressBook, ClearNet, Network};
|
||||||
|
@ -403,7 +403,7 @@ async fn get_info(
|
||||||
let (database_size, free_space) = blockchain::database_size(&mut state.blockchain_read).await?;
|
let (database_size, free_space) = blockchain::database_size(&mut state.blockchain_read).await?;
|
||||||
let (database_size, free_space) = if restricted {
|
let (database_size, free_space) = if restricted {
|
||||||
// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L131-L134>
|
// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L131-L134>
|
||||||
fn round_up(value: u64, quantum: u64) -> u64 {
|
const fn round_up(value: u64, quantum: u64) -> u64 {
|
||||||
(value + quantum - 1) / quantum * quantum
|
(value + quantum - 1) / quantum * quantum
|
||||||
}
|
}
|
||||||
let database_size = round_up(database_size, 5 * 1024 * 1024 * 1024);
|
let database_size = round_up(database_size, 5 * 1024 * 1024 * 1024);
|
||||||
|
@ -931,20 +931,31 @@ async fn calc_pow(
|
||||||
let block = Block::read(&mut block_blob.as_slice())?;
|
let block = Block::read(&mut block_blob.as_slice())?;
|
||||||
let seed_hash = helper::hex_to_hash(request.seed_hash)?;
|
let seed_hash = helper::hex_to_hash(request.seed_hash)?;
|
||||||
|
|
||||||
// let pow_hash = blockchain_manager::calculate_pow(
|
let block_weight = todo!("calculate block weight");
|
||||||
// &mut state.blockchain_manager,
|
|
||||||
// hardfork,
|
|
||||||
// request.height,
|
|
||||||
// block,
|
|
||||||
// seed_hash,
|
|
||||||
// )
|
|
||||||
// .await?;
|
|
||||||
|
|
||||||
// let hex = hex::encode(pow_hash);
|
let median_for_block_reward = blockchain_context::context(&mut state.blockchain_context)
|
||||||
|
.await?
|
||||||
|
.unchecked_blockchain_context()
|
||||||
|
.context_to_verify_block
|
||||||
|
.median_weight_for_block_reward;
|
||||||
|
|
||||||
let hex = todo!();
|
if cuprate_consensus_rules::blocks::check_block_weight(block_weight, median_for_block_reward)
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
|
return Err(anyhow!("Block blob size is too big, rejecting block"));
|
||||||
|
}
|
||||||
|
|
||||||
Ok(CalcPowResponse { pow_hash: hex })
|
let pow_hash = blockchain_context::calculate_pow(
|
||||||
|
&mut state.blockchain_context,
|
||||||
|
hardfork,
|
||||||
|
block,
|
||||||
|
seed_hash,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let pow_hash = hex::encode(pow_hash);
|
||||||
|
|
||||||
|
Ok(CalcPowResponse { pow_hash })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L3542-L3551>
|
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L3542-L3551>
|
||||||
|
@ -964,8 +975,9 @@ async fn add_aux_pow(
|
||||||
mut state: CupratedRpcHandler,
|
mut state: CupratedRpcHandler,
|
||||||
request: AddAuxPowRequest,
|
request: AddAuxPowRequest,
|
||||||
) -> Result<AddAuxPowResponse, Error> {
|
) -> Result<AddAuxPowResponse, Error> {
|
||||||
let hex = hex::decode(request.blocktemplate_blob)?;
|
if request.aux_pow.is_empty() {
|
||||||
let block_template = Block::read(&mut hex.as_slice())?;
|
return Err(anyhow!("Empty `aux_pow` vector"));
|
||||||
|
}
|
||||||
|
|
||||||
let aux_pow = request
|
let aux_pow = request
|
||||||
.aux_pow
|
.aux_pow
|
||||||
|
@ -975,31 +987,177 @@ async fn add_aux_pow(
|
||||||
let hash = helper::hex_to_hash(aux.hash)?;
|
let hash = helper::hex_to_hash(aux.hash)?;
|
||||||
Ok(cuprate_types::AuxPow { id, hash })
|
Ok(cuprate_types::AuxPow { id, hash })
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, Error>>()?;
|
.collect::<Result<Box<[_]>, Error>>()?;
|
||||||
|
// Some of the code below requires that the
|
||||||
|
// `.len()` of certain containers are the same.
|
||||||
|
// Boxed slices are used over `Vec` to slightly
|
||||||
|
// safe-guard against accidently pushing to it.
|
||||||
|
|
||||||
let resp = todo!();
|
// --- BEGIN AUX POW IMPL ---
|
||||||
// let resp =
|
|
||||||
// blockchain_manager::add_aux_pow(&mut state.blockchain_manager, block_template, aux_pow)
|
|
||||||
// .await?;
|
|
||||||
|
|
||||||
let blocktemplate_blob = hex::encode(resp.blocktemplate_blob);
|
// Original impl:
|
||||||
let blockhashing_blob = hex::encode(resp.blockhashing_blob);
|
// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2110-L2206>
|
||||||
let merkle_root = hex::encode(resp.merkle_root);
|
|
||||||
let aux_pow = resp
|
let len = aux_pow.len();
|
||||||
.aux_pow
|
|
||||||
.into_iter()
|
let mut path_domain = 1_usize;
|
||||||
|
while 1 << path_domain < len {
|
||||||
|
path_domain += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut nonce = 0_u32;
|
||||||
|
let mut collision = true;
|
||||||
|
let mut slots: Box<[u32]> = vec![0; len].into_boxed_slice(); // INVARIANT: this must be the same `.len()` as `aux_pow`
|
||||||
|
|
||||||
|
for n in 0..u32::MAX {
|
||||||
|
nonce = n;
|
||||||
|
|
||||||
|
let slot_seen: Vec<bool> = vec![false; len];
|
||||||
|
|
||||||
|
collision = false;
|
||||||
|
|
||||||
|
slots.iter_mut().for_each(|i| *i = u32::MAX);
|
||||||
|
|
||||||
|
for i in &mut slots {
|
||||||
|
let slot_u32: u32 = todo!("const uint32_t slot = cryptonote::get_aux_slot(aux_pow[idx].first, nonce, aux_pow.size());");
|
||||||
|
let slot = u32_to_usize(slot_u32);
|
||||||
|
|
||||||
|
if slot >= len {
|
||||||
|
return Err(anyhow!("Computed slot is out of range"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if slot_seen[slot] {
|
||||||
|
collision = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
slot_seen[slot] = true;
|
||||||
|
*i = slot_u32;
|
||||||
|
}
|
||||||
|
|
||||||
|
if !collision {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let nonce = nonce;
|
||||||
|
let slots = slots;
|
||||||
|
|
||||||
|
if collision {
|
||||||
|
return Err(anyhow!("Failed to find a suitable nonce"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: use iterator version.
|
||||||
|
let (aux_pow_id_raw, aux_pow_raw) = {
|
||||||
|
let mut aux_pow_id_raw = Vec::<[u8; 32]>::with_capacity(len);
|
||||||
|
let mut aux_pow_raw = Vec::<[u8; 32]>::with_capacity(len);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
aux_pow.len(),
|
||||||
|
slots.len(),
|
||||||
|
"these need to be the same or else the below .zip() doesn't make sense"
|
||||||
|
);
|
||||||
|
|
||||||
|
for (aux_pow, slot) in aux_pow.iter().zip(&slots) {
|
||||||
|
if u32_to_usize(*slot) >= len {
|
||||||
|
return Err(anyhow!("Slot value out of range"));
|
||||||
|
}
|
||||||
|
|
||||||
|
aux_pow_id_raw.push(aux_pow.id);
|
||||||
|
aux_pow_raw.push(aux_pow.hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
slots.len(),
|
||||||
|
aux_pow_raw.len(),
|
||||||
|
"these need to be the same or else the below .zip() doesn't make sense"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
aux_pow_raw.len(),
|
||||||
|
aux_pow_id_raw.len(),
|
||||||
|
"these need to be the same or else the below .zip() doesn't make sense"
|
||||||
|
);
|
||||||
|
|
||||||
|
for (slot, aux_pow) in slots.iter().zip(&aux_pow) {
|
||||||
|
let slot = u32_to_usize(*slot);
|
||||||
|
|
||||||
|
if slot >= len {
|
||||||
|
return Err(anyhow!("Slot value out of range"));
|
||||||
|
}
|
||||||
|
|
||||||
|
aux_pow_raw[slot] = aux_pow.hash;
|
||||||
|
aux_pow_id_raw[slot] = aux_pow.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
(
|
||||||
|
aux_pow_id_raw.into_boxed_slice(),
|
||||||
|
aux_pow_raw.into_boxed_slice(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
fn tree_hash(aux_pow_raw: &[[u8; 32]]) -> [u8; 32] {
|
||||||
|
todo!("https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2163")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_mm_depth(aux_pow_len: usize, nonce: u32) -> u64 {
|
||||||
|
todo!("https://github.com/monero-project/monero/blob/893916ad091a92e765ce3241b94e706ad012b62a/src/cryptonote_basic/merge_mining.cpp#L74")
|
||||||
|
}
|
||||||
|
|
||||||
|
let merkle_root = tree_hash(aux_pow_raw.as_ref());
|
||||||
|
let merkle_tree_depth = encode_mm_depth(len, nonce);
|
||||||
|
|
||||||
|
let block_template = {
|
||||||
|
let hex = hex::decode(request.blocktemplate_blob)?;
|
||||||
|
Block::read(&mut hex.as_slice())?
|
||||||
|
};
|
||||||
|
|
||||||
|
fn remove_field_from_tx_extra() -> Result<(), ()> {
|
||||||
|
todo!("https://github.com/monero-project/monero/blob/master/src/cryptonote_basic/cryptonote_format_utils.cpp#L767")
|
||||||
|
}
|
||||||
|
|
||||||
|
if remove_field_from_tx_extra().is_err() {
|
||||||
|
return Err(anyhow!("Error removing existing merkle root"));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_mm_merkle_root_to_tx_extra() -> Result<(), ()> {
|
||||||
|
todo!("https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2189
|
||||||
|
")
|
||||||
|
}
|
||||||
|
|
||||||
|
if add_mm_merkle_root_to_tx_extra().is_err() {
|
||||||
|
return Err(anyhow!("Error adding merkle root"));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn invalidate_hashes() {
|
||||||
|
// block_template.invalidate_hashes();
|
||||||
|
// block_template.miner_tx.invalidate_hashes();
|
||||||
|
// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2195-L2196>
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidate_hashes();
|
||||||
|
|
||||||
|
let blocktemplate_blob = block_template.serialize();
|
||||||
|
let blockhashing_blob = block_template.serialize_pow_hash();
|
||||||
|
|
||||||
|
let blocktemplate_blob = hex::encode(blocktemplate_blob);
|
||||||
|
let blockhashing_blob = hex::encode(blockhashing_blob);
|
||||||
|
let merkle_root = hex::encode(merkle_root);
|
||||||
|
let aux_pow = IntoIterator::into_iter(aux_pow) // must be explicit due to `boxed_slice_into_iter`
|
||||||
.map(|aux| AuxPow {
|
.map(|aux| AuxPow {
|
||||||
id: hex::encode(aux.id),
|
id: hex::encode(aux.id),
|
||||||
hash: hex::encode(aux.hash),
|
hash: hex::encode(aux.hash),
|
||||||
})
|
})
|
||||||
.collect::<Vec<AuxPow>>();
|
.collect::<Vec<AuxPow>>();
|
||||||
|
|
||||||
|
// --- END AUX POW IMPL ---
|
||||||
|
|
||||||
Ok(AddAuxPowResponse {
|
Ok(AddAuxPowResponse {
|
||||||
base: ResponseBase::OK,
|
base: ResponseBase::OK,
|
||||||
blocktemplate_blob,
|
blocktemplate_blob,
|
||||||
blockhashing_blob,
|
blockhashing_blob,
|
||||||
merkle_root,
|
merkle_root,
|
||||||
merkle_tree_depth: resp.merkle_tree_depth,
|
merkle_tree_depth,
|
||||||
aux_pow,
|
aux_pow,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,17 +73,22 @@ pub(crate) async fn fee_estimate(
|
||||||
pub(crate) async fn calculate_pow(
|
pub(crate) async fn calculate_pow(
|
||||||
blockchain_context: &mut BlockChainContextService,
|
blockchain_context: &mut BlockChainContextService,
|
||||||
hardfork: HardFork,
|
hardfork: HardFork,
|
||||||
height: u64,
|
block: Block,
|
||||||
block: Box<Block>,
|
|
||||||
seed_hash: [u8; 32],
|
seed_hash: [u8; 32],
|
||||||
) -> Result<[u8; 32], Error> {
|
) -> Result<[u8; 32], Error> {
|
||||||
|
let Some(height) = block.number() else {
|
||||||
|
return Err(anyhow!("block is missing height"));
|
||||||
|
};
|
||||||
|
|
||||||
|
let block = Box::new(block);
|
||||||
|
|
||||||
let BlockChainContextResponse::CalculatePow(hash) = blockchain_context
|
let BlockChainContextResponse::CalculatePow(hash) = blockchain_context
|
||||||
.ready()
|
.ready()
|
||||||
.await
|
.await
|
||||||
.map_err(|e| anyhow!(e))?
|
.map_err(|e| anyhow!(e))?
|
||||||
.call(BlockChainContextRequest::CalculatePow {
|
.call(BlockChainContextRequest::CalculatePow {
|
||||||
hardfork,
|
hardfork,
|
||||||
height: u64_to_usize(height),
|
height,
|
||||||
block,
|
block,
|
||||||
seed_hash,
|
seed_hash,
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue