mirror of
https://github.com/darkrenaissance/darkfi.git
synced 2026-04-28 03:00:18 -04:00
blockchain/monero: Add async serialization
This commit is contained in:
@@ -16,9 +16,13 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::io::{Error, Read, Result, Write};
|
||||
use std::io::{self, Cursor, Error, Read, Write};
|
||||
|
||||
use darkfi_serial::{Decodable, Encodable, ReadExt};
|
||||
use async_trait::async_trait;
|
||||
use darkfi_serial::{
|
||||
AsyncDecodable, AsyncEncodable, AsyncRead, AsyncReadExt, AsyncWrite, Decodable, Encodable,
|
||||
ReadExt,
|
||||
};
|
||||
use monero::{
|
||||
consensus::{Decodable as XmrDecodable, Encodable as XmrEncodable},
|
||||
Hash,
|
||||
@@ -36,7 +40,7 @@ pub struct MerkleProof {
|
||||
}
|
||||
|
||||
impl Encodable for MerkleProof {
|
||||
fn encode<S: Write>(&self, s: &mut S) -> Result<usize> {
|
||||
fn encode<S: Write>(&self, s: &mut S) -> io::Result<usize> {
|
||||
let mut n = 0;
|
||||
|
||||
let len = self.branch.len() as u8;
|
||||
@@ -52,8 +56,28 @@ impl Encodable for MerkleProof {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl AsyncEncodable for MerkleProof {
|
||||
async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> io::Result<usize> {
|
||||
let mut n = 0;
|
||||
|
||||
let len = self.branch.len() as u8;
|
||||
n += len.encode_async(s).await?;
|
||||
|
||||
for hash in &self.branch {
|
||||
let mut buf = vec![];
|
||||
(*hash).consensus_encode(&mut buf)?;
|
||||
n += buf.encode_async(s).await?;
|
||||
}
|
||||
|
||||
n += self.path_bitmap.encode_async(s).await?;
|
||||
|
||||
Ok(n)
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for MerkleProof {
|
||||
fn decode<D: Read>(d: &mut D) -> Result<Self> {
|
||||
fn decode<D: Read>(d: &mut D) -> io::Result<Self> {
|
||||
let len: u8 = d.read_u8()?;
|
||||
let mut branch = Vec::with_capacity(len as usize);
|
||||
|
||||
@@ -67,6 +91,26 @@ impl Decodable for MerkleProof {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl AsyncDecodable for MerkleProof {
|
||||
async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> io::Result<Self> {
|
||||
let len: u8 = d.read_u8_async().await?;
|
||||
let mut branch = Vec::with_capacity(len as usize);
|
||||
|
||||
for _ in 0..len {
|
||||
let buf: Vec<u8> = AsyncDecodable::decode_async(d).await?;
|
||||
let mut buf = Cursor::new(buf);
|
||||
branch.push(
|
||||
Hash::consensus_decode(&mut buf).map_err(|_| Error::other("Invalid XMR hash"))?,
|
||||
);
|
||||
}
|
||||
|
||||
let path_bitmap: u32 = AsyncDecodable::decode_async(d).await?;
|
||||
|
||||
Ok(Self { branch, path_bitmap })
|
||||
}
|
||||
}
|
||||
|
||||
impl MerkleProof {
|
||||
pub fn try_construct(branch: Vec<Hash>, path_bitmap: u32) -> Option<Self> {
|
||||
if branch.len() >= MAX_MERKLE_TREE_PROOF_SIZE {
|
||||
|
||||
@@ -16,9 +16,10 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
use std::io::{Error, Read, Result, Write};
|
||||
use std::io::{self, Cursor, Error, Read, Write};
|
||||
|
||||
use darkfi_serial::{Decodable, Encodable};
|
||||
use async_trait::async_trait;
|
||||
use darkfi_serial::{AsyncDecodable, AsyncEncodable, AsyncRead, AsyncWrite, Decodable, Encodable};
|
||||
use monero::{
|
||||
blockdata::transaction::RawExtraField,
|
||||
consensus::{Decodable as XmrDecodable, Encodable as XmrEncodable},
|
||||
@@ -61,13 +62,14 @@ pub struct MoneroPowData {
|
||||
}
|
||||
|
||||
impl Encodable for MoneroPowData {
|
||||
fn encode<S: Write>(&self, s: &mut S) -> Result<usize> {
|
||||
fn encode<S: Write>(&self, s: &mut S) -> io::Result<usize> {
|
||||
let mut n = 0;
|
||||
|
||||
n += self.header.consensus_encode(s)?;
|
||||
n += self.randomx_key.encode(s)?;
|
||||
n += self.transaction_count.encode(s)?;
|
||||
n += self.merkle_root.as_fixed_bytes().encode(s)?;
|
||||
n += self.merkle_root.consensus_encode(s)?;
|
||||
n += self.coinbase_merkle_proof.encode(s)?;
|
||||
|
||||
// This is an incomplete hasher. Dump it from memory
|
||||
// and write it down. We can restore it the same way.
|
||||
@@ -81,16 +83,47 @@ impl Encodable for MoneroPowData {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl AsyncEncodable for MoneroPowData {
|
||||
async fn encode_async<S: AsyncWrite + Unpin + Send>(&self, s: &mut S) -> io::Result<usize> {
|
||||
let mut n = 0;
|
||||
|
||||
let mut buf = vec![];
|
||||
self.header.consensus_encode(&mut buf)?;
|
||||
n += buf.encode_async(s).await?;
|
||||
|
||||
n += self.randomx_key.encode_async(s).await?;
|
||||
n += self.transaction_count.encode_async(s).await?;
|
||||
|
||||
let mut buf = vec![];
|
||||
self.merkle_root.consensus_encode(&mut buf)?;
|
||||
n += buf.encode_async(s).await?;
|
||||
|
||||
n += self.coinbase_merkle_proof.encode_async(s).await?;
|
||||
|
||||
// This is an incomplete hasher. Dump it from memory
|
||||
// and write it down. We can restore it the same way.
|
||||
let buf = keccak_to_bytes(&self.coinbase_tx_hasher);
|
||||
n += buf.encode_async(s).await?;
|
||||
|
||||
n += self.coinbase_tx_extra.0.encode_async(s).await?;
|
||||
n += self.aux_chain_merkle_proof.encode_async(s).await?;
|
||||
|
||||
Ok(n)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Decodable for MoneroPowData {
|
||||
fn decode<D: Read>(d: &mut D) -> Result<Self> {
|
||||
fn decode<D: Read>(d: &mut D) -> io::Result<Self> {
|
||||
let header =
|
||||
BlockHeader::consensus_decode(d).map_err(|_| Error::other("Invalid XMR header"))?;
|
||||
|
||||
let randomx_key: [u8; 64] = Decodable::decode(d)?;
|
||||
let transaction_count: u16 = Decodable::decode(d)?;
|
||||
|
||||
let merkle_root: [u8; 32] = Decodable::decode(d)?;
|
||||
let merkle_root = Hash::from_slice(&merkle_root);
|
||||
let merkle_root =
|
||||
Hash::consensus_decode(d).map_err(|_| Error::other("Invamid XMR hash"))?;
|
||||
|
||||
let coinbase_merkle_proof: MerkleProof = Decodable::decode(d)?;
|
||||
|
||||
@@ -99,7 +132,6 @@ impl Decodable for MoneroPowData {
|
||||
|
||||
let coinbase_tx_extra: Vec<u8> = Decodable::decode(d)?;
|
||||
let coinbase_tx_extra = RawExtraField(coinbase_tx_extra);
|
||||
|
||||
let aux_chain_merkle_proof: MerkleProof = Decodable::decode(d)?;
|
||||
|
||||
Ok(Self {
|
||||
@@ -115,6 +147,44 @@ impl Decodable for MoneroPowData {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl AsyncDecodable for MoneroPowData {
|
||||
async fn decode_async<D: AsyncRead + Unpin + Send>(d: &mut D) -> io::Result<Self> {
|
||||
let buf: Vec<u8> = AsyncDecodable::decode_async(d).await?;
|
||||
let mut buf = Cursor::new(buf);
|
||||
let header = BlockHeader::consensus_decode(&mut buf)
|
||||
.map_err(|_| Error::other("Invalid XMR header"))?;
|
||||
|
||||
let randomx_key: [u8; 64] = AsyncDecodable::decode_async(d).await?;
|
||||
let transaction_count: u16 = AsyncDecodable::decode_async(d).await?;
|
||||
|
||||
let buf: Vec<u8> = AsyncDecodable::decode_async(d).await?;
|
||||
let mut buf = Cursor::new(buf);
|
||||
let merkle_root =
|
||||
Hash::consensus_decode(&mut buf).map_err(|_| Error::other("Invalid XMR hash"))?;
|
||||
|
||||
let coinbase_merkle_proof: MerkleProof = AsyncDecodable::decode_async(d).await?;
|
||||
|
||||
let buf: Vec<u8> = AsyncDecodable::decode_async(d).await?;
|
||||
let coinbase_tx_hasher = keccak_from_bytes(&buf);
|
||||
|
||||
let coinbase_tx_extra: Vec<u8> = AsyncDecodable::decode_async(d).await?;
|
||||
let coinbase_tx_extra = RawExtraField(coinbase_tx_extra);
|
||||
let aux_chain_merkle_proof: MerkleProof = AsyncDecodable::decode_async(d).await?;
|
||||
|
||||
Ok(Self {
|
||||
header,
|
||||
randomx_key,
|
||||
transaction_count,
|
||||
merkle_root,
|
||||
coinbase_merkle_proof,
|
||||
coinbase_tx_hasher,
|
||||
coinbase_tx_extra,
|
||||
aux_chain_merkle_proof,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl MoneroPowData {
|
||||
/// Returns true if the coinbase Merkle proof produces the `merkle_root` hash.
|
||||
pub fn is_coinbase_valid_merkle_root(&self) -> bool {
|
||||
|
||||
Reference in New Issue
Block a user