mmproxy/monero: Implement blocktemplate modification for merge mining

This commit is contained in:
parazyd
2023-11-05 11:53:15 +01:00
parent ed4ac96e44
commit 3eed132fa4
3 changed files with 36 additions and 9 deletions

1
Cargo.lock generated
View File

@@ -1761,6 +1761,7 @@ dependencies = [
"darkfi-serial",
"easy-parallel",
"epee-encoding",
"hex",
"log",
"monero",
"serde",

View File

@@ -21,6 +21,7 @@ monero = {version = "0.19.0", features = ["full"]}
surf = "2.3.2"
# Encoding
hex = "0.4.3"
url = "2.4.1"
uuid = {version = "1.5.0", features = ["v4"]}

View File

@@ -29,6 +29,7 @@ use darkfi::{
Error, Result,
};
use log::{debug, error};
use monero::blockdata::transaction::{ExtraField, RawExtraField, SubField::MergeMining};
use super::MiningProxy;
@@ -137,21 +138,30 @@ impl MiningProxy {
return JsonError::new(InvalidParams, None, id).into()
};
let Some(reserve_size) = params["reserve_size"].get::<f64>() else {
let Some(_reserve_size) = params["reserve_size"].get::<f64>() else {
return JsonError::new(InvalidParams, None, id).into()
};
// The MergeMining tag and anything else going into ExtraField should
// be done here, so we can pass the correct reserve_size.
// Create the Merge Mining Tag
let mm_tag = MergeMining(Some(monero::VarInt(32)), monero::Hash([0_u8; 32]));
let tx_extra: RawExtraField = ExtraField(vec![mm_tag]).into();
let reserve_size = tx_extra.0.len();
// Create request
let req = JsonRequest::new(
"get_block_template",
HashMap::from([
("wallet_address".to_string(), (*wallet_address).clone().into()),
("reserve_size".to_string(), (*reserve_size).into()),
("reserve_size".to_string(), (reserve_size as f64).into()),
])
.into(),
);
let rep = match self.oneshot_request(req).await {
// Get block template from monerod
let mut rep = match self.oneshot_request(req).await {
Ok(v) => v,
Err(e) => {
error!(target: "rpc::monero::get_block_template", "{}", e);
@@ -159,15 +169,30 @@ impl MiningProxy {
}
};
// TODO: Now we have to modify the block template.
// Now we have to modify the block template:
// * reserve_size has to be the size of the data we want to put in the block
// * blocktemplate_blob has the reserved bytes, they're in the tx_extra field
// of the coinbase tx, which is then hashed with other transactions into
// merkle root hash which is what's in the blockhashing_blob
// * When blocktemplate_blob is modified, blockhashing_blob has to be updated too
// * The coinbase tx from monerod should be replaced with the one we create
// containing the merged mining data/info
// of the coinbase tx, which is then hashed with other txs into Merkle root
// which is what's in the blockhashing_blob
// Deserialize the block template
let mut block_template = monero::consensus::deserialize::<monero::Block>(
&hex::decode(rep["result"]["blocktemplate_blob"].get::<String>().unwrap()).unwrap(),
)
.unwrap();
// Modify the coinbase tx
block_template.miner_tx.prefix.extra = tx_extra;
// Replace the blocktemplate blob
rep["result"]["blocktemplate_blob"] =
JsonValue::String(hex::encode(monero::consensus::serialize(&block_template)));
// Replace the blockhashing blob
rep["result"]["blockhashing_blob"] =
JsonValue::String(hex::encode(&block_template.serialize_hashable()));
// Pass the modified response to the client
JsonResponse::new(rep, id).into()
}