Skip to content

Commit

Permalink
Change monero consensus encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
SWvheerden committed Aug 18, 2022
1 parent e21dfdb commit f7115d1
Show file tree
Hide file tree
Showing 11 changed files with 197 additions and 135 deletions.
35 changes: 28 additions & 7 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion applications/tari_merge_mining_proxy/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ async fn main() -> Result<(), anyhow::Error> {

let config = MergeMiningProxyConfig::load_from(&cfg)?;

error!(target: LOG_TARGET, "Configuration: {:?}", config);
info!(target: LOG_TARGET, "Configuration: {:?}", config);
let client = reqwest::Client::builder()
.connect_timeout(Duration::from_secs(5))
.timeout(Duration::from_secs(10))
Expand Down
11 changes: 4 additions & 7 deletions applications/tari_merge_mining_proxy/src/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,9 @@ use jsonrpc::error::StandardError;
use reqwest::{ResponseBuilderExt, Url};
use serde_json as json;
use tari_app_grpc::tari_rpc as grpc;
use tari_core::proof_of_work::{
monero_difficulty,
monero_rx,
monero_rx::FixedByteArray,
randomx_factory::RandomXFactory,
use tari_core::{
consensus::ConsensusEncoding,
proof_of_work::{monero_difficulty, monero_rx, monero_rx::FixedByteArray, randomx_factory::RandomXFactory},
};
use tari_utilities::hex::Hex;
use tracing::{debug, error, info, instrument, trace, warn};
Expand Down Expand Up @@ -269,8 +267,7 @@ impl InnerService {

let header_mut = block_data.tari_block.header.as_mut().unwrap();
let height = header_mut.height;
header_mut.pow.as_mut().unwrap().pow_data = monero_rx::serialize(&monero_data);

monero_data.consensus_encode(&mut header_mut.pow.as_mut().unwrap().pow_data)?;
let tari_header = header_mut.clone().try_into().map_err(MmProxyError::ConversionError)?;
let mut base_node_client = self.base_node_client.clone();
let start = Instant::now();
Expand Down
2 changes: 1 addition & 1 deletion base_layer/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ integer-encoding = "3.0.2"
lmdb-zero = "0.4.4"
log = "0.4"
log-mdc = "0.1.0"
monero = { version = "^0.13.0", features = ["serde_support"], optional = true }
monero = { git = "https://github.com/tari-project/monero-rs.git", features = ["serde"], optional = true }
newtype-ops = "0.1.4"
num-traits = "0.2.15"
num-derive = "0.3.3"
Expand Down
16 changes: 16 additions & 0 deletions base_layer/core/src/consensus/consensus_encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,22 @@ impl<T: ConsensusEncoding + ConsensusEncodingSized + ?Sized> ToConsensusBytes fo
}
}

pub trait FromConsensusBytes<T>
where T: ConsensusDecoding + ?Sized
{
fn from_consensus_bytes(bytes: &[u8]) -> io::Result<T>;
}

impl<T: ConsensusDecoding + ?Sized> FromConsensusBytes<T> for T {
fn from_consensus_bytes(mut bytes: &[u8]) -> io::Result<T> {
let decoded = Self::consensus_decode(&mut bytes)?;
if !bytes.is_empty() {
return Err(io::Error::new(io::ErrorKind::InvalidData, "Extra bytes at end of data"));
}
Ok(decoded)
}
}

#[cfg(test)]
pub mod test {
use super::*;
Expand Down
1 change: 1 addition & 0 deletions base_layer/core/src/consensus/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub use consensus_encoding::{
ConsensusEncodingSized,
ConsensusHasher,
DomainSeparatedConsensusHasher,
FromConsensusBytes,
MaxSizeBytes,
MaxSizeVec,
ToConsensusBytes,
Expand Down
54 changes: 31 additions & 23 deletions base_layer/core/src/proof_of_work/monero_rx/fixed_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,17 @@
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::{convert::TryFrom, io, ops::Deref};

use monero::{
consensus::{encode, Decodable, Encodable},
VarInt,
use std::{
convert::TryFrom,
io,
io::{Read, Write},
ops::Deref,
};

use tari_utilities::{ByteArray, ByteArrayError};

use crate::consensus::{ConsensusDecoding, ConsensusEncoding};

const MAX_ARR_SIZE: usize = 63;

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -109,33 +112,38 @@ impl ByteArray for FixedByteArray {
}
}

impl Decodable for FixedByteArray {
fn consensus_decode<D: io::Read>(d: &mut D) -> Result<Self, encode::Error> {
#[allow(clippy::cast_possible_truncation)]
let len = VarInt::consensus_decode(d)?.0 as usize;
impl ConsensusDecoding for FixedByteArray {
fn consensus_decode<R: Read>(reader: &mut R) -> Result<Self, io::Error> {
let mut buf = [0u8; 1];
reader.read_exact(&mut buf)?;
let len = buf[0] as usize;
if len > MAX_ARR_SIZE {
return Err(encode::Error::ParseFailed(
"length exceeded maximum of 64-bytes for FixedByteArray",
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
format!("length exceeded maximum of 64-bytes for FixedByteArray: {}", len),
));
}
let mut ret = FixedByteArray::new();
for _ in 0..len {
// PANIC: Cannot happen because len has been checked
ret.push(Decodable::consensus_decode(d)?);
let mut buf = [0u8; 1];
reader.read_exact(&mut buf)?;
ret.push(buf[0]);
}
Ok(ret)
}
}

impl Encodable for FixedByteArray {
fn consensus_encode<E: io::Write>(&self, e: &mut E) -> Result<usize, io::Error> {
self.as_slice().consensus_encode(e)
impl ConsensusEncoding for FixedByteArray {
fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<(), io::Error> {
writer.write_all(&[self.len][..])?;
writer.write_all(&self.elems[0..self.len()])?;
Ok(())
}
}

#[cfg(test)]
mod test {
use monero::consensus;
use tari_utilities::hex::Hex;

use super::*;
Expand Down Expand Up @@ -167,9 +175,11 @@ mod test {

#[test]
fn serialize_deserialize() {
let data = consensus::serialize(&FixedByteArray::from_hex("ffffffffffffffffffffffffff").unwrap());
let arr = FixedByteArray::from_hex("ffffffffffffffffffffffffff").unwrap();
let mut data = Vec::new();
arr.consensus_encode(&mut data).unwrap();
assert_eq!(data.len(), 13 + 1);
let arr = consensus::deserialize::<FixedByteArray>(&data).unwrap();
let arr = FixedByteArray::consensus_decode(&mut data.as_slice()).unwrap();
assert!(arr.iter().all(|b| *b == 0xff));
}

Expand All @@ -181,19 +191,17 @@ mod test {
assert_eq!(arr.len(), MAX_ARR_SIZE);

buf[0] = 64;
let err = FixedByteArray::consensus_decode(&mut io::Cursor::new(buf)).unwrap_err();
assert!(matches!(err, encode::Error::ParseFailed(_)));
let _err = FixedByteArray::consensus_decode(&mut io::Cursor::new(buf)).unwrap_err();

// VarInt encoding that doesnt terminate, but _would_ represent a number < MAX_ARR_SIZE
buf[0] = 0b1000000;
buf[1] = 0b1000000;
let err = FixedByteArray::consensus_decode(&mut io::Cursor::new(buf)).unwrap_err();
assert!(matches!(err, encode::Error::ParseFailed(_)));
let _err = FixedByteArray::consensus_decode(&mut io::Cursor::new(buf)).unwrap_err();
}

#[test]
fn capacity_overflow_does_not_panic() {
let data = &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f];
let _result = consensus::deserialize::<FixedByteArray>(data);
let _result = FixedByteArray::consensus_decode(&mut data.as_slice()).unwrap_err();
}
}
33 changes: 22 additions & 11 deletions base_layer/core/src/proof_of_work/monero_rx/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,10 @@ mod test {
};

use super::*;
use crate::proof_of_work::{monero_rx::fixed_array::FixedByteArray, PowAlgorithm, ProofOfWork};
use crate::{
consensus::ConsensusEncoding,
proof_of_work::{monero_rx::fixed_array::FixedByteArray, PowAlgorithm, ProofOfWork},
};

// This tests checks the hash of monero-rs
#[test]
Expand Down Expand Up @@ -319,7 +322,8 @@ mod test {
coinbase_merkle_proof,
coinbase_tx: block.miner_tx,
};
let serialized = consensus::serialize(&monero_data);
let mut serialized = Vec::new();
monero_data.consensus_encode(&mut serialized).unwrap();
let pow = ProofOfWork {
pow_algo: PowAlgorithm::Monero,
pow_data: serialized,
Expand Down Expand Up @@ -379,7 +383,8 @@ mod test {
coinbase_merkle_proof,
coinbase_tx: block.miner_tx,
};
let serialized = consensus::serialize(&monero_data);
let mut serialized = Vec::new();
monero_data.consensus_encode(&mut serialized).unwrap();
let pow = ProofOfWork {
pow_algo: PowAlgorithm::Monero,
pow_data: serialized,
Expand Down Expand Up @@ -426,7 +431,9 @@ mod test {
coinbase_merkle_proof,
coinbase_tx: block.miner_tx,
};
let serialized = consensus::serialize(&monero_data);

let mut serialized = Vec::new();
monero_data.consensus_encode(&mut serialized).unwrap();
let pow = ProofOfWork {
pow_algo: PowAlgorithm::Monero,
pow_data: serialized,
Expand Down Expand Up @@ -459,7 +466,7 @@ mod test {
nonce: 0,
pow: ProofOfWork::default(),
};
let hash = Hash::null_hash();
let hash = Hash::null();
append_merge_mining_tag(&mut block, hash).unwrap();
let count = 1 + (u16::try_from(block.tx_hashes.len()).unwrap());
let mut hashes = Vec::with_capacity(count as usize);
Expand All @@ -480,7 +487,8 @@ mod test {
coinbase_merkle_proof,
coinbase_tx: block.miner_tx,
};
let serialized = consensus::serialize(&monero_data);
let mut serialized = Vec::new();
monero_data.consensus_encode(&mut serialized).unwrap();
let pow = ProofOfWork {
pow_algo: PowAlgorithm::Monero,
pow_data: serialized,
Expand Down Expand Up @@ -534,7 +542,8 @@ mod test {
coinbase_merkle_proof,
coinbase_tx: Default::default(),
};
let serialized = consensus::serialize(&monero_data);
let mut serialized = Vec::new();
monero_data.consensus_encode(&mut serialized).unwrap();
let pow = ProofOfWork {
pow_algo: PowAlgorithm::Monero,
pow_data: serialized,
Expand Down Expand Up @@ -568,10 +577,11 @@ mod test {
randomx_key: FixedByteArray::default(),
transaction_count: 1,
merkle_root: Default::default(),
coinbase_merkle_proof: create_merkle_proof(&[Hash::null_hash()], &Hash::null_hash()).unwrap(),
coinbase_merkle_proof: create_merkle_proof(&[Hash::null()], &Hash::null()).unwrap(),
coinbase_tx: Default::default(),
};
let serialized = consensus::serialize(&monero_data);
let mut serialized = Vec::new();
monero_data.consensus_encode(&mut serialized).unwrap();
let pow = ProofOfWork {
pow_algo: PowAlgorithm::Monero,
pow_data: serialized,
Expand Down Expand Up @@ -621,11 +631,12 @@ mod test {
header: block.header,
randomx_key: FixedByteArray::from_bytes(&from_hex(&seed_hash).unwrap()).unwrap(),
transaction_count: count,
merkle_root: Hash::null_hash(),
merkle_root: Hash::null(),
coinbase_merkle_proof,
coinbase_tx: block.miner_tx,
};
let serialized = consensus::serialize(&monero_data);
let mut serialized = Vec::new();
monero_data.consensus_encode(&mut serialized).unwrap();
let pow = ProofOfWork {
pow_algo: PowAlgorithm::Monero,
pow_data: serialized,
Expand Down
Loading

0 comments on commit f7115d1

Please sign in to comment.