mirror of
https://github.com/serai-dex/serai.git
synced 2025-01-05 10:29:40 +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
|
.txs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|res| {
|
.map(|res| {
|
||||||
let tx = Transaction::deserialize(&mut std::io::Cursor::new(rpc_hex(
|
let tx = Transaction::deserialize::<&[u8]>(
|
||||||
if !res.as_hex.is_empty() { &res.as_hex } else { &res.pruned_as_hex },
|
&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) {
|
.map_err(|_| match hash_hex(&res.tx_hash) {
|
||||||
Ok(hash) => RpcError::InvalidTransaction(hash),
|
Ok(hash) => RpcError::InvalidTransaction(hash),
|
||||||
Err(err) => err,
|
Err(err) => err,
|
||||||
|
@ -287,27 +288,52 @@ impl Rpc {
|
||||||
Ok(txs.txs[0].block_height)
|
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)]
|
#[derive(Deserialize, Debug)]
|
||||||
struct BlockResponse {
|
struct BlockResponse {
|
||||||
blob: String,
|
blob: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
let block: BlockResponse =
|
let res: BlockResponse =
|
||||||
self.json_rpc_call("get_block", Some(json!({ "height": height }))).await?;
|
self.json_rpc_call("get_block", Some(json!({ "hash": hex::encode(hash) }))).await?;
|
||||||
Ok(
|
|
||||||
Block::deserialize(&mut std::io::Cursor::new(rpc_hex(&block.blob)?))
|
Block::deserialize::<&[u8]>(&mut rpc_hex(&res.blob)?.as_ref())
|
||||||
.expect("Monero returned a block we couldn't deserialize"),
|
.map_err(|_| RpcError::InvalidNode)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_block_transactions(&self, height: usize) -> Result<Vec<Transaction>, RpcError> {
|
pub async fn get_block_by_number(&self, number: usize) -> Result<Block, RpcError> {
|
||||||
let block = self.get_block(height).await?;
|
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];
|
let mut res = vec![block.miner_tx];
|
||||||
res.extend(self.get_transactions(&block.txs).await?);
|
res.extend(self.get_transactions(&block.txs).await?);
|
||||||
Ok(res)
|
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.
|
/// Get the output indexes of the specified transaction.
|
||||||
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> {
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
|
@ -407,13 +433,8 @@ impl Rpc {
|
||||||
&outs
|
&outs
|
||||||
.outs
|
.outs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|out| {
|
.map(|out| rpc_hex(&out.txid)?.try_into().map_err(|_| RpcError::InvalidNode))
|
||||||
rpc_hex(&out.txid)
|
.collect::<Result<Vec<_>, _>>()?,
|
||||||
.expect("Monero returned an invalidly encoded hash")
|
|
||||||
.try_into()
|
|
||||||
.expect("Monero returned an invalid sized hash")
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use core::ops::BitXor;
|
use core::ops::BitXor;
|
||||||
use std::io::{self, Read, Write, Cursor};
|
use std::io::{self, Read, Write};
|
||||||
|
|
||||||
use zeroize::Zeroize;
|
use zeroize::Zeroize;
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ impl Extra {
|
||||||
pub(crate) fn payment_id(&self) -> Option<PaymentId> {
|
pub(crate) fn payment_id(&self) -> Option<PaymentId> {
|
||||||
for field in &self.0 {
|
for field in &self.0 {
|
||||||
if let ExtraField::Nonce(data) = field {
|
if let ExtraField::Nonce(data) = field {
|
||||||
return PaymentId::deserialize(&mut Cursor::new(data)).ok();
|
return PaymentId::deserialize::<&[u8]>(&mut data.as_ref()).ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use std::io::Cursor;
|
|
||||||
|
|
||||||
use zeroize::{Zeroize, ZeroizeOnDrop};
|
use zeroize::{Zeroize, ZeroizeOnDrop};
|
||||||
|
|
||||||
use curve25519_dalek::{constants::ED25519_BASEPOINT_TABLE, scalar::Scalar, edwards::EdwardsPoint};
|
use curve25519_dalek::{constants::ED25519_BASEPOINT_TABLE, scalar::Scalar, edwards::EdwardsPoint};
|
||||||
|
@ -232,7 +230,7 @@ impl<O: Clone + Zeroize> Timelocked<O> {
|
||||||
impl Scanner {
|
impl Scanner {
|
||||||
/// Scan a transaction to discover the received outputs.
|
/// Scan a transaction to discover the received outputs.
|
||||||
pub fn scan_transaction(&mut self, tx: &Transaction) -> Timelocked<ReceivedOutput> {
|
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 keys;
|
||||||
let extra = if let Ok(extra) = extra {
|
let extra = if let Ok(extra) = extra {
|
||||||
keys = extra.keys();
|
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 height = rpc.get_height().await.unwrap();
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
while !found {
|
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) {
|
found = match block.txs.iter().find(|&&x| x == tx_hash) {
|
||||||
Some(_) => true,
|
Some(_) => true,
|
||||||
None => {
|
None => {
|
||||||
|
@ -69,7 +69,7 @@ pub async fn get_miner_tx_output(rpc: &Rpc, view: &ViewPair) -> SpendableOutput
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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)
|
scanner.scan(rpc, &block).await.unwrap().swap_remove(0).ignore_timelock().swap_remove(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue