Implement Block types

Finishes updating the RPC to not use monero, tests now pass
This commit is contained in:
Luke Parker 2022-05-21 21:35:25 -04:00
parent 3282b19536
commit 703b18c6e8
No known key found for this signature in database
GPG key ID: F9F1386DB1E119B6
4 changed files with 85 additions and 23 deletions

64
coins/monero/src/block.rs Normal file
View file

@ -0,0 +1,64 @@
use crate::{
serialize::*,
transaction::Transaction
};
pub struct BlockHeader {
pub major_version: u64,
pub minor_version: u64,
pub timestamp: u64,
pub previous: [u8; 32],
pub nonce: u32
}
impl BlockHeader {
pub fn serialize<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
write_varint(&self.major_version, w)?;
write_varint(&self.minor_version, w)?;
write_varint(&self.timestamp, w)?;
w.write_all(&self.previous)?;
w.write_all(&self.nonce.to_le_bytes())
}
pub fn deserialize<R: std::io::Read>(r: &mut R) -> std::io::Result<BlockHeader> {
Ok(
BlockHeader {
major_version: read_varint(r)?,
minor_version: read_varint(r)?,
timestamp: read_varint(r)?,
previous: { let mut previous = [0; 32]; r.read_exact(&mut previous)?; previous },
nonce: { let mut nonce = [0; 4]; r.read_exact(&mut nonce)?; u32::from_le_bytes(nonce) }
}
)
}
}
pub struct Block {
pub header: BlockHeader,
pub miner_tx: Transaction,
pub txs: Vec<[u8; 32]>
}
impl Block {
pub fn serialize<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
self.header.serialize(w)?;
self.miner_tx.serialize(w)?;
write_varint(&self.txs.len().try_into().unwrap(), w)?;
for tx in &self.txs {
w.write_all(tx)?;
}
Ok(())
}
pub fn deserialize<R: std::io::Read>(r: &mut R) -> std::io::Result<Block> {
Ok(
Block {
header: BlockHeader::deserialize(r)?,
miner_tx: Transaction::deserialize(r)?,
txs: (0 .. read_varint(r)?).map(
|_| { let mut tx = [0; 32]; r.read_exact(&mut tx).map(|_| tx) }
).collect::<Result<_, _>>()?
}
)
}
}

View file

@ -17,10 +17,11 @@ mod serialize;
pub mod bulletproofs;
pub mod clsag;
pub mod rpc;
pub mod transaction;
pub mod wallet;
pub mod block;
pub mod rpc;
pub mod wallet;
#[cfg(test)]
mod tests;

View file

@ -9,7 +9,7 @@ use serde_json::json;
use reqwest;
use crate::transaction::{Input, Transaction};
use crate::{transaction::{Input, Transaction}, block::Block};
#[derive(Deserialize, Debug)]
pub struct EmptyResponse {}
@ -97,7 +97,11 @@ impl Rpc {
Ok(self.rpc_call::<Option<()>, HeightResponse>("get_height", None).await?.height)
}
pub async fn get_transactions(&self, hashes: Vec<[u8; 32]>) -> Result<Vec<Transaction>, RpcError> {
pub async fn get_transactions(&self, hashes: &[[u8; 32]]) -> Result<Vec<Transaction>, RpcError> {
if hashes.len() == 0 {
return Ok(vec![]);
}
#[derive(Deserialize, Debug)]
struct TransactionResponse {
as_hex: String,
@ -135,38 +139,31 @@ impl Rpc {
)
}
/*
pub async fn get_block(&self, height: usize) -> Result<Block, RpcError> {
#[derive(Deserialize, Debug)]
struct BlockResponse {
json: String
blob: String
}
let block: JsonRpcResponse<BlockResponse> = self.rpc_call("json_rpc", Some(json!({
"method": "get_block",
"params": {
"height": height
"height": dbg!(height)
}
}))).await?;
Ok(
deserialize(
&rpc_hex(&block.result.blob)?
Block::deserialize(
&mut std::io::Cursor::new(rpc_hex(&block.result.blob)?)
).expect("Monero returned a block we couldn't deserialize")
)
}
*/
pub async fn get_block_transactions(&self, height: usize) -> Result<Vec<Transaction>, RpcError> {
/*
let block = self.get_block(height).await?;
let mut res = vec![block.miner_tx];
if block.tx_hashes.len() != 0 {
res.extend(self.get_transactions(block.tx_hashes.iter().map(|hash| hash.0).collect()).await?);
}
res.extend(self.get_transactions(&block.txs).await?);
Ok(res)
*/
Ok(vec![])
}
pub async fn get_o_indexes(&self, hash: [u8; 32]) -> Result<Vec<u64>, RpcError> {
@ -220,10 +217,10 @@ impl Rpc {
}))).await?;
let txs = self.get_transactions(
outs.outs.iter().map(|out|
&outs.outs.iter().map(|out|
rpc_hex(&out.txid).expect("Monero returned an invalidly encoded hash")
.try_into().expect("Monero returned an invalid sized hash")
).collect()
).collect::<Vec<_>>()
).await?;
// TODO: Support time based lock times. These shouldn't be needed, and it may be painful to
// get the median time for the given height, yet we do need to in order to be complete

View file

@ -20,7 +20,7 @@ impl Input {
pub fn serialize<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
match self {
Input::Gen(height) => {
w.write_all(&[0])?;
w.write_all(&[255])?;
write_varint(height, w)
},
@ -34,17 +34,17 @@ impl Input {
}
pub fn deserialize<R: std::io::Read>(r: &mut R) -> std::io::Result<Input> {
let mut variant = [0; 1];
let mut variant = [0];
r.read_exact(&mut variant)?;
Ok(
match variant[0] {
0 => Input::Gen(read_varint(r)?),
255 => Input::Gen(read_varint(r)?),
2 => Input::ToKey {
amount: read_varint(r)?,
key_offsets: read_vec(read_varint, r)?,
key_image: read_point(r)?
},
_ => Err(std::io::Error::new(std::io::ErrorKind::Other, "Tried to deserialize unknown/unused output type"))?
_ => Err(std::io::Error::new(std::io::ErrorKind::Other, "Tried to deserialize unknown/unused input type"))?
}
)
}
@ -70,7 +70,7 @@ impl Output {
pub fn deserialize<R: std::io::Read>(r: &mut R) -> std::io::Result<Output> {
let amount = read_varint(r)?;
let mut tag = [0; 1];
let mut tag = [0];
r.read_exact(&mut tag)?;
if (tag[0] != 2) && (tag[0] != 3) {
Err(std::io::Error::new(std::io::ErrorKind::Other, "Tried to deserialize unknown/unused output type"))?;