Skip to content

Commit 94bcc11

Browse files
committed
getblockmeta: allow request by height
1 parent de4bb3f commit 94bcc11

File tree

3 files changed

+82
-48
lines changed

3 files changed

+82
-48
lines changed

Diff for: client/src/client.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@ pub struct BlockMeta {
4444
pub tx_meta: Vec<TxEntry>,
4545
}
4646

47-
#[derive(Clone, Serialize, Deserialize, Encode, Decode)]
47+
#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)]
4848
pub struct TxEntry {
4949
#[serde(flatten)]
5050
pub changeset: TxChangeSet,
5151
#[serde(skip_serializing_if = "Option::is_none", flatten)]
5252
pub tx: Option<TxData>,
5353
}
5454

55-
#[derive(Clone, Serialize, Deserialize, Encode, Decode)]
55+
#[derive(Debug, Clone, Serialize, Deserialize, Encode, Decode)]
5656
pub struct TxData {
5757
pub position: u32,
5858
pub raw: Bytes,

Diff for: client/src/rpc.rs

+79-45
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,20 @@ pub struct RootAnchor {
8080
pub block: ChainAnchor,
8181
}
8282

83+
#[derive(Debug, Clone, Serialize, Deserialize)]
84+
#[serde(untagged)]
85+
pub enum BlockIdentifier {
86+
Hash(BlockHash),
87+
Height(u32),
88+
}
89+
90+
#[derive(Debug, Clone, Serialize, Deserialize)]
91+
pub struct BlockMetaWithHash {
92+
pub hash: BlockHash,
93+
pub height: u32,
94+
pub tx_meta: Vec<TxEntry>,
95+
}
96+
8397
pub enum ChainStateCommand {
8498
CheckPackage {
8599
txs: Vec<String>,
@@ -105,8 +119,8 @@ pub enum ChainStateCommand {
105119
resp: Responder<anyhow::Result<Option<TxEntry>>>,
106120
},
107121
GetBlockMeta {
108-
block_hash: BlockHash,
109-
resp: Responder<anyhow::Result<Option<BlockMeta>>>,
122+
block_identifier: BlockIdentifier,
123+
resp: Responder<anyhow::Result<BlockMetaWithHash>>,
110124
},
111125
EstimateBid {
112126
target: usize,
@@ -179,8 +193,8 @@ pub trait Rpc {
179193
#[method(name = "getblockmeta")]
180194
async fn get_block_meta(
181195
&self,
182-
block_hash: BlockHash,
183-
) -> Result<Option<BlockMeta>, ErrorObjectOwned>;
196+
block_identifier: BlockIdentifier,
197+
) -> Result<BlockMetaWithHash, ErrorObjectOwned>;
184198

185199
#[method(name = "gettxmeta")]
186200
async fn get_tx_meta(&self, txid: Txid) -> Result<Option<TxEntry>, ErrorObjectOwned>;
@@ -599,19 +613,6 @@ impl WalletManager {
599613
Ok(())
600614
}
601615

602-
pub async fn get_block_hash(
603-
&self,
604-
client: &reqwest::Client,
605-
height: u32,
606-
) -> anyhow::Result<BlockId> {
607-
let hash = self
608-
.rpc
609-
.send_json(&client, &self.rpc.get_block_hash(height))
610-
.await?;
611-
612-
Ok(BlockId { height, hash })
613-
}
614-
615616
async fn get_wallet_start_block(&self, client: &reqwest::Client) -> anyhow::Result<BlockId> {
616617
let count: i32 = self
617618
.rpc
@@ -797,11 +798,11 @@ impl RpcServer for RpcServerImpl {
797798

798799
async fn get_block_meta(
799800
&self,
800-
block_hash: BlockHash,
801-
) -> Result<Option<BlockMeta>, ErrorObjectOwned> {
801+
block_identifier: BlockIdentifier,
802+
) -> Result<BlockMetaWithHash, ErrorObjectOwned> {
802803
let data = self
803804
.store
804-
.get_block_meta(block_hash)
805+
.get_block_meta(block_identifier)
805806
.await
806807
.map_err(|error| ErrorObjectOwned::owned(-1, error.to_string(), None::<String>))?;
807808

@@ -1072,55 +1073,74 @@ impl AsyncChainState {
10721073
BlockHash::from_str(info.get("blockhash").and_then(|t| t.as_str()).ok_or_else(
10731074
|| anyhow!("Could not retrieve block hash for tx (is it in the mempool?)"),
10741075
)?)?;
1075-
let block = Self::get_indexed_block(index, &block_hash, client, rpc, chain_state).await?;
1076+
let block = Self::get_indexed_block(
1077+
index,
1078+
BlockIdentifier::Hash(block_hash),
1079+
client,
1080+
rpc,
1081+
chain_state,
1082+
)
1083+
.await?;
10761084

1077-
if let Some(block) = block {
1078-
return Ok(block
1079-
.tx_meta
1080-
.into_iter()
1081-
.find(|tx| &tx.changeset.txid == txid));
1082-
}
1083-
Ok(None)
1085+
Ok(block
1086+
.tx_meta
1087+
.into_iter()
1088+
.find(|tx| &tx.changeset.txid == txid))
10841089
}
10851090

10861091
async fn get_indexed_block(
10871092
index: &mut Option<LiveSnapshot>,
1088-
block_hash: &BlockHash,
1093+
block_identifier: BlockIdentifier,
10891094
client: &reqwest::Client,
10901095
rpc: &BitcoinRpc,
10911096
chain_state: &mut LiveSnapshot,
1092-
) -> Result<Option<BlockMeta>, anyhow::Error> {
1097+
) -> Result<BlockMetaWithHash, anyhow::Error> {
10931098
let index = index
10941099
.as_mut()
10951100
.ok_or_else(|| anyhow!("block index must be enabled"))?;
1096-
let hash = BaseHash::from_slice(block_hash.as_ref());
1097-
let block: Option<BlockMeta> = index
1098-
.get(hash)
1099-
.context("Could not fetch block from index")?;
1101+
let hash = match block_identifier {
1102+
BlockIdentifier::Hash(hash) => hash,
1103+
BlockIdentifier::Height(height) => rpc
1104+
.send_json(client, &rpc.get_block_hash(height))
1105+
.await
1106+
.map_err(|e| anyhow!("Could not retrieve block hash ({})", e))?,
1107+
};
11001108

1101-
if let Some(block_set) = block {
1102-
return Ok(Some(block_set));
1109+
if let Some(BlockMeta { height, tx_meta }) = index
1110+
.get(BaseHash::from_slice(hash.as_ref()))
1111+
.context("Could not fetch block from index")?
1112+
{
1113+
return Ok(BlockMetaWithHash {
1114+
hash,
1115+
height,
1116+
tx_meta,
1117+
});
11031118
}
11041119

11051120
let info: serde_json::Value = rpc
1106-
.send_json(client, &rpc.get_block_header(block_hash))
1121+
.send_json(client, &rpc.get_block_header(&hash))
11071122
.await
11081123
.map_err(|e| anyhow!("Could not retrieve block ({})", e))?;
11091124

11101125
let height = info
11111126
.get("height")
11121127
.and_then(|t| t.as_u64())
1128+
.and_then(|h| u32::try_from(h).ok())
11131129
.ok_or_else(|| anyhow!("Could not retrieve block height"))?;
11141130

11151131
let tip = chain_state.tip.read().expect("read meta").clone();
1116-
if height > tip.height as u64 {
1132+
if height > tip.height {
11171133
return Err(anyhow!(
11181134
"Spaces is syncing at height {}, requested block height {}",
11191135
tip.height,
11201136
height
11211137
));
11221138
}
1123-
Ok(None)
1139+
Ok(BlockMetaWithHash {
1140+
hash,
1141+
height,
1142+
tx_meta: Vec::new(),
1143+
})
11241144
}
11251145

11261146
pub async fn handle_command(
@@ -1168,10 +1188,18 @@ impl AsyncChainState {
11681188
.context("could not fetch spaceout");
11691189
let _ = resp.send(result);
11701190
}
1171-
ChainStateCommand::GetBlockMeta { block_hash, resp } => {
1172-
let res =
1173-
Self::get_indexed_block(block_index, &block_hash, client, rpc, chain_state)
1174-
.await;
1191+
ChainStateCommand::GetBlockMeta {
1192+
block_identifier,
1193+
resp,
1194+
} => {
1195+
let res = Self::get_indexed_block(
1196+
block_index,
1197+
block_identifier,
1198+
client,
1199+
rpc,
1200+
chain_state,
1201+
)
1202+
.await;
11751203
let _ = resp.send(res);
11761204
}
11771205
ChainStateCommand::GetTxMeta { txid, resp } => {
@@ -1479,10 +1507,16 @@ impl AsyncChainState {
14791507
resp_rx.await?
14801508
}
14811509

1482-
pub async fn get_block_meta(&self, block_hash: BlockHash) -> anyhow::Result<Option<BlockMeta>> {
1510+
pub async fn get_block_meta(
1511+
&self,
1512+
block_identifier: BlockIdentifier,
1513+
) -> anyhow::Result<BlockMetaWithHash> {
14831514
let (resp, resp_rx) = oneshot::channel();
14841515
self.sender
1485-
.send(ChainStateCommand::GetBlockMeta { block_hash, resp })
1516+
.send(ChainStateCommand::GetBlockMeta {
1517+
block_identifier,
1518+
resp,
1519+
})
14861520
.await?;
14871521
resp_rx.await?
14881522
}

Diff for: protocol/src/validate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::{
1717
#[derive(Debug, Clone)]
1818
pub struct Validator {}
1919

20-
#[derive(Clone)]
20+
#[derive(Debug, Clone)]
2121
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2222
#[cfg_attr(feature = "bincode", derive(Encode, Decode))]
2323
/// A `TxChangeSet` captures all resulting state changes.

0 commit comments

Comments
 (0)