mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-03 17:40:34 +00:00
Exposed a hash-based API for accessing blocks
Also corrects a few panics, which shouldn't have been present, and unnecessary Cursor uses.
This commit is contained in:
parent
814a9a8d35
commit
1d6df0099c
4 changed files with 45 additions and 26 deletions
|
@ -249,9 +249,10 @@ impl Rpc {
|
|||
.txs
|
||||
.iter()
|
||||
.map(|res| {
|
||||
let tx = Transaction::deserialize(&mut std::io::Cursor::new(rpc_hex(
|
||||
if !res.as_hex.is_empty() { &res.as_hex } else { &res.pruned_as_hex },
|
||||
)?))
|
||||
let tx = Transaction::deserialize::<&[u8]>(
|
||||
&mut rpc_hex(if !res.as_hex.is_empty() { &res.as_hex } else { &res.pruned_as_hex })?
|
||||
.as_ref(),
|
||||
)
|
||||
.map_err(|_| match hash_hex(&res.tx_hash) {
|
||||
Ok(hash) => RpcError::InvalidTransaction(hash),
|
||||
Err(err) => err,
|
||||
|
@ -287,27 +288,52 @@ impl Rpc {
|
|||
Ok(txs.txs[0].block_height)
|
||||
}
|
||||
|
||||
pub async fn get_block(&self, height: usize) -> Result<Block, RpcError> {
|
||||
pub async fn get_block_hash(&self, number: usize) -> Result<[u8; 32], RpcError> {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct BlockHeaderResponse {
|
||||
hash: String,
|
||||
}
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct BlockHeaderByHeightResponse {
|
||||
block_header: BlockHeaderResponse,
|
||||
}
|
||||
|
||||
let header: BlockHeaderByHeightResponse =
|
||||
self.json_rpc_call("get_block_header_by_height", Some(json!({ "height": number }))).await?;
|
||||
rpc_hex(&header.block_header.hash)?.try_into().map_err(|_| RpcError::InvalidNode)
|
||||
}
|
||||
|
||||
pub async fn get_block(&self, hash: [u8; 32]) -> Result<Block, RpcError> {
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct BlockResponse {
|
||||
blob: String,
|
||||
}
|
||||
|
||||
let block: BlockResponse =
|
||||
self.json_rpc_call("get_block", Some(json!({ "height": height }))).await?;
|
||||
Ok(
|
||||
Block::deserialize(&mut std::io::Cursor::new(rpc_hex(&block.blob)?))
|
||||
.expect("Monero returned a block we couldn't deserialize"),
|
||||
)
|
||||
let res: BlockResponse =
|
||||
self.json_rpc_call("get_block", Some(json!({ "hash": hex::encode(hash) }))).await?;
|
||||
|
||||
Block::deserialize::<&[u8]>(&mut rpc_hex(&res.blob)?.as_ref())
|
||||
.map_err(|_| RpcError::InvalidNode)
|
||||
}
|
||||
|
||||
pub async fn get_block_transactions(&self, height: usize) -> Result<Vec<Transaction>, RpcError> {
|
||||
let block = self.get_block(height).await?;
|
||||
pub async fn get_block_by_number(&self, number: usize) -> Result<Block, RpcError> {
|
||||
self.get_block(self.get_block_hash(number).await?).await
|
||||
}
|
||||
|
||||
pub async fn get_block_transactions(&self, hash: [u8; 32]) -> Result<Vec<Transaction>, RpcError> {
|
||||
let block = self.get_block(hash).await?;
|
||||
let mut res = vec![block.miner_tx];
|
||||
res.extend(self.get_transactions(&block.txs).await?);
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
pub async fn get_block_transactions_by_number(
|
||||
&self,
|
||||
number: usize,
|
||||
) -> Result<Vec<Transaction>, RpcError> {
|
||||
self.get_block_transactions(self.get_block_hash(number).await?).await
|
||||
}
|
||||
|
||||
/// Get the output indexes of the specified transaction.
|
||||
pub async fn get_o_indexes(&self, hash: [u8; 32]) -> Result<Vec<u64>, RpcError> {
|
||||
#[derive(Serialize, Debug)]
|
||||
|
@ -407,13 +433,8 @@ impl Rpc {
|
|||
&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::<Vec<_>>(),
|
||||
.map(|out| rpc_hex(&out.txid)?.try_into().map_err(|_| RpcError::InvalidNode))
|
||||
.collect::<Result<Vec<_>, _>>()?,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use core::ops::BitXor;
|
||||
use std::io::{self, Read, Write, Cursor};
|
||||
use std::io::{self, Read, Write};
|
||||
|
||||
use zeroize::Zeroize;
|
||||
|
||||
|
@ -127,7 +127,7 @@ impl Extra {
|
|||
pub(crate) fn payment_id(&self) -> Option<PaymentId> {
|
||||
for field in &self.0 {
|
||||
if let ExtraField::Nonce(data) = field {
|
||||
return PaymentId::deserialize(&mut Cursor::new(data)).ok();
|
||||
return PaymentId::deserialize::<&[u8]>(&mut data.as_ref()).ok();
|
||||
}
|
||||
}
|
||||
None
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::io::Cursor;
|
||||
|
||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||
|
||||
use curve25519_dalek::{constants::ED25519_BASEPOINT_TABLE, scalar::Scalar, edwards::EdwardsPoint};
|
||||
|
@ -232,7 +230,7 @@ impl<O: Clone + Zeroize> Timelocked<O> {
|
|||
impl Scanner {
|
||||
/// Scan a transaction to discover the received outputs.
|
||||
pub fn scan_transaction(&mut self, tx: &Transaction) -> Timelocked<ReceivedOutput> {
|
||||
let extra = Extra::deserialize(&mut Cursor::new(&tx.prefix.extra));
|
||||
let extra = Extra::deserialize::<&[u8]>(&mut tx.prefix.extra.as_ref());
|
||||
let keys;
|
||||
let extra = if let Ok(extra) = extra {
|
||||
keys = extra.keys();
|
||||
|
|
|
@ -43,7 +43,7 @@ pub async fn mine_until_unlocked(rpc: &Rpc, addr: &str, tx_hash: [u8; 32]) {
|
|||
let mut height = rpc.get_height().await.unwrap();
|
||||
let mut found = false;
|
||||
while !found {
|
||||
let block = rpc.get_block(height - 1).await.unwrap();
|
||||
let block = rpc.get_block_by_number(height - 1).await.unwrap();
|
||||
found = match block.txs.iter().find(|&&x| x == tx_hash) {
|
||||
Some(_) => true,
|
||||
None => {
|
||||
|
@ -69,7 +69,7 @@ pub async fn get_miner_tx_output(rpc: &Rpc, view: &ViewPair) -> SpendableOutput
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let block = rpc.get_block(start).await.unwrap();
|
||||
let block = rpc.get_block_by_number(start).await.unwrap();
|
||||
scanner.scan(rpc, &block).await.unwrap().swap_remove(0).ignore_timelock().swap_remove(0)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue