mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Implement Block types
Finishes updating the RPC to not use monero, tests now pass
This commit is contained in:
64
coins/monero/src/block.rs
Normal file
64
coins/monero/src/block.rs
Normal 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<_, _>>()?
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,10 +17,11 @@ mod serialize;
|
|||||||
pub mod bulletproofs;
|
pub mod bulletproofs;
|
||||||
pub mod clsag;
|
pub mod clsag;
|
||||||
|
|
||||||
pub mod rpc;
|
|
||||||
pub mod transaction;
|
pub mod transaction;
|
||||||
pub mod wallet;
|
pub mod block;
|
||||||
|
|
||||||
|
pub mod rpc;
|
||||||
|
pub mod wallet;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use serde_json::json;
|
|||||||
|
|
||||||
use reqwest;
|
use reqwest;
|
||||||
|
|
||||||
use crate::transaction::{Input, Transaction};
|
use crate::{transaction::{Input, Transaction}, block::Block};
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct EmptyResponse {}
|
pub struct EmptyResponse {}
|
||||||
@@ -97,7 +97,11 @@ impl Rpc {
|
|||||||
Ok(self.rpc_call::<Option<()>, HeightResponse>("get_height", None).await?.height)
|
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)]
|
#[derive(Deserialize, Debug)]
|
||||||
struct TransactionResponse {
|
struct TransactionResponse {
|
||||||
as_hex: String,
|
as_hex: String,
|
||||||
@@ -135,38 +139,31 @@ impl Rpc {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
pub async fn get_block(&self, height: usize) -> Result<Block, RpcError> {
|
pub async fn get_block(&self, height: usize) -> Result<Block, RpcError> {
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
struct BlockResponse {
|
struct BlockResponse {
|
||||||
json: String
|
blob: String
|
||||||
}
|
}
|
||||||
|
|
||||||
let block: JsonRpcResponse<BlockResponse> = self.rpc_call("json_rpc", Some(json!({
|
let block: JsonRpcResponse<BlockResponse> = self.rpc_call("json_rpc", Some(json!({
|
||||||
"method": "get_block",
|
"method": "get_block",
|
||||||
"params": {
|
"params": {
|
||||||
"height": height
|
"height": dbg!(height)
|
||||||
}
|
}
|
||||||
}))).await?;
|
}))).await?;
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
deserialize(
|
Block::deserialize(
|
||||||
&rpc_hex(&block.result.blob)?
|
&mut std::io::Cursor::new(rpc_hex(&block.result.blob)?)
|
||||||
).expect("Monero returned a block we couldn't deserialize")
|
).expect("Monero returned a block we couldn't deserialize")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
pub async fn get_block_transactions(&self, height: usize) -> Result<Vec<Transaction>, RpcError> {
|
pub async fn get_block_transactions(&self, height: usize) -> Result<Vec<Transaction>, RpcError> {
|
||||||
/*
|
|
||||||
let block = self.get_block(height).await?;
|
let block = self.get_block(height).await?;
|
||||||
let mut res = vec![block.miner_tx];
|
let mut res = vec![block.miner_tx];
|
||||||
if block.tx_hashes.len() != 0 {
|
res.extend(self.get_transactions(&block.txs).await?);
|
||||||
res.extend(self.get_transactions(block.tx_hashes.iter().map(|hash| hash.0).collect()).await?);
|
|
||||||
}
|
|
||||||
Ok(res)
|
Ok(res)
|
||||||
*/
|
|
||||||
Ok(vec![])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_o_indexes(&self, hash: [u8; 32]) -> Result<Vec<u64>, RpcError> {
|
pub async fn get_o_indexes(&self, hash: [u8; 32]) -> Result<Vec<u64>, RpcError> {
|
||||||
@@ -220,10 +217,10 @@ impl Rpc {
|
|||||||
}))).await?;
|
}))).await?;
|
||||||
|
|
||||||
let txs = self.get_transactions(
|
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")
|
rpc_hex(&out.txid).expect("Monero returned an invalidly encoded hash")
|
||||||
.try_into().expect("Monero returned an invalid sized hash")
|
.try_into().expect("Monero returned an invalid sized hash")
|
||||||
).collect()
|
).collect::<Vec<_>>()
|
||||||
).await?;
|
).await?;
|
||||||
// TODO: Support time based lock times. These shouldn't be needed, and it may be painful to
|
// 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
|
// get the median time for the given height, yet we do need to in order to be complete
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ impl Input {
|
|||||||
pub fn serialize<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
|
pub fn serialize<W: std::io::Write>(&self, w: &mut W) -> std::io::Result<()> {
|
||||||
match self {
|
match self {
|
||||||
Input::Gen(height) => {
|
Input::Gen(height) => {
|
||||||
w.write_all(&[0])?;
|
w.write_all(&[255])?;
|
||||||
write_varint(height, w)
|
write_varint(height, w)
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -34,17 +34,17 @@ impl Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn deserialize<R: std::io::Read>(r: &mut R) -> std::io::Result<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)?;
|
r.read_exact(&mut variant)?;
|
||||||
Ok(
|
Ok(
|
||||||
match variant[0] {
|
match variant[0] {
|
||||||
0 => Input::Gen(read_varint(r)?),
|
255 => Input::Gen(read_varint(r)?),
|
||||||
2 => Input::ToKey {
|
2 => Input::ToKey {
|
||||||
amount: read_varint(r)?,
|
amount: read_varint(r)?,
|
||||||
key_offsets: read_vec(read_varint, r)?,
|
key_offsets: read_vec(read_varint, r)?,
|
||||||
key_image: read_point(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> {
|
pub fn deserialize<R: std::io::Read>(r: &mut R) -> std::io::Result<Output> {
|
||||||
let amount = read_varint(r)?;
|
let amount = read_varint(r)?;
|
||||||
let mut tag = [0; 1];
|
let mut tag = [0];
|
||||||
r.read_exact(&mut tag)?;
|
r.read_exact(&mut tag)?;
|
||||||
if (tag[0] != 2) && (tag[0] != 3) {
|
if (tag[0] != 2) && (tag[0] != 3) {
|
||||||
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 output type"))?;
|
||||||
|
|||||||
Reference in New Issue
Block a user