@@ -80,6 +80,20 @@ pub struct RootAnchor {
80
80
pub block : ChainAnchor ,
81
81
}
82
82
83
+ #[ derive( Debug , Clone , Serialize , Deserialize ) ]
84
+ #[ serde( untagged) ]
85
+ pub enum HeightOrHash {
86
+ Hash ( BlockHash ) ,
87
+ Height ( u32 ) ,
88
+ }
89
+
90
+ #[ derive( Debug , Clone , Serialize , Deserialize ) ]
91
+ pub struct BlockMetaWithHash {
92
+ pub hash : BlockHash ,
93
+ #[ serde( flatten) ]
94
+ pub block_meta : BlockMeta ,
95
+ }
96
+
83
97
pub enum ChainStateCommand {
84
98
CheckPackage {
85
99
txs : Vec < String > ,
@@ -105,8 +119,8 @@ pub enum ChainStateCommand {
105
119
resp : Responder < anyhow:: Result < Option < TxEntry > > > ,
106
120
} ,
107
121
GetBlockMeta {
108
- block_hash : BlockHash ,
109
- resp : Responder < anyhow:: Result < Option < BlockMeta > > > ,
122
+ height_or_hash : HeightOrHash ,
123
+ resp : Responder < anyhow:: Result < BlockMetaWithHash > > ,
110
124
} ,
111
125
EstimateBid {
112
126
target : usize ,
@@ -179,8 +193,8 @@ pub trait Rpc {
179
193
#[ method( name = "getblockmeta" ) ]
180
194
async fn get_block_meta (
181
195
& self ,
182
- block_hash : BlockHash ,
183
- ) -> Result < Option < BlockMeta > , ErrorObjectOwned > ;
196
+ height_or_hash : HeightOrHash ,
197
+ ) -> Result < BlockMetaWithHash , ErrorObjectOwned > ;
184
198
185
199
#[ method( name = "gettxmeta" ) ]
186
200
async fn get_tx_meta ( & self , txid : Txid ) -> Result < Option < TxEntry > , ErrorObjectOwned > ;
@@ -602,19 +616,6 @@ impl WalletManager {
602
616
Ok ( ( ) )
603
617
}
604
618
605
- pub async fn get_block_hash (
606
- & self ,
607
- client : & reqwest:: Client ,
608
- height : u32 ,
609
- ) -> anyhow:: Result < BlockId > {
610
- let hash = self
611
- . rpc
612
- . send_json ( & client, & self . rpc . get_block_hash ( height) )
613
- . await ?;
614
-
615
- Ok ( BlockId { height, hash } )
616
- }
617
-
618
619
async fn get_wallet_start_block ( & self , client : & reqwest:: Client ) -> anyhow:: Result < BlockId > {
619
620
let count: i32 = self
620
621
. rpc
@@ -800,11 +801,11 @@ impl RpcServer for RpcServerImpl {
800
801
801
802
async fn get_block_meta (
802
803
& self ,
803
- block_hash : BlockHash ,
804
- ) -> Result < Option < BlockMeta > , ErrorObjectOwned > {
804
+ height_or_hash : HeightOrHash ,
805
+ ) -> Result < BlockMetaWithHash , ErrorObjectOwned > {
805
806
let data = self
806
807
. store
807
- . get_block_meta ( block_hash )
808
+ . get_block_meta ( height_or_hash )
808
809
. await
809
810
. map_err ( |error| ErrorObjectOwned :: owned ( -1 , error. to_string ( ) , None :: < String > ) ) ?;
810
811
@@ -1075,55 +1076,76 @@ impl AsyncChainState {
1075
1076
BlockHash :: from_str ( info. get ( "blockhash" ) . and_then ( |t| t. as_str ( ) ) . ok_or_else (
1076
1077
|| anyhow ! ( "Could not retrieve block hash for tx (is it in the mempool?)" ) ,
1077
1078
) ?) ?;
1078
- let block = Self :: get_indexed_block ( index, & block_hash, client, rpc, chain_state) . await ?;
1079
+ let block = Self :: get_indexed_block (
1080
+ index,
1081
+ HeightOrHash :: Hash ( block_hash) ,
1082
+ client,
1083
+ rpc,
1084
+ chain_state,
1085
+ )
1086
+ . await ?;
1079
1087
1080
- if let Some ( block) = block {
1081
- return Ok ( block
1082
- . tx_meta
1083
- . into_iter ( )
1084
- . find ( |tx| & tx. changeset . txid == txid) ) ;
1085
- }
1086
- Ok ( None )
1088
+ Ok ( block
1089
+ . block_meta
1090
+ . tx_meta
1091
+ . into_iter ( )
1092
+ . find ( |tx| & tx. changeset . txid == txid) )
1087
1093
}
1088
1094
1089
1095
async fn get_indexed_block (
1090
1096
index : & mut Option < LiveSnapshot > ,
1091
- block_hash : & BlockHash ,
1097
+ height_or_hash : HeightOrHash ,
1092
1098
client : & reqwest:: Client ,
1093
1099
rpc : & BitcoinRpc ,
1094
1100
chain_state : & mut LiveSnapshot ,
1095
- ) -> Result < Option < BlockMeta > , anyhow:: Error > {
1101
+ ) -> Result < BlockMetaWithHash , anyhow:: Error > {
1096
1102
let index = index
1097
1103
. as_mut ( )
1098
1104
. ok_or_else ( || anyhow ! ( "block index must be enabled" ) ) ?;
1099
- let hash = BaseHash :: from_slice ( block_hash. as_ref ( ) ) ;
1100
- let block: Option < BlockMeta > = index
1101
- . get ( hash)
1102
- . context ( "Could not fetch block from index" ) ?;
1105
+ let hash = match height_or_hash {
1106
+ HeightOrHash :: Hash ( hash) => hash,
1107
+ HeightOrHash :: Height ( height) => rpc
1108
+ . send_json ( client, & rpc. get_block_hash ( height) )
1109
+ . await
1110
+ . map_err ( |e| anyhow ! ( "Could not retrieve block hash ({})" , e) ) ?,
1111
+ } ;
1103
1112
1104
- if let Some ( block_set) = block {
1105
- return Ok ( Some ( block_set) ) ;
1113
+ if let Some ( block_meta) = index
1114
+ . get ( BaseHash :: from_slice ( hash. as_ref ( ) ) )
1115
+ . context ( "Could not fetch block from index" ) ?
1116
+ {
1117
+ return Ok ( BlockMetaWithHash {
1118
+ hash,
1119
+ block_meta,
1120
+ } ) ;
1106
1121
}
1107
1122
1108
1123
let info: serde_json:: Value = rpc
1109
- . send_json ( client, & rpc. get_block_header ( block_hash ) )
1124
+ . send_json ( client, & rpc. get_block_header ( & hash ) )
1110
1125
. await
1111
1126
. map_err ( |e| anyhow ! ( "Could not retrieve block ({})" , e) ) ?;
1112
1127
1113
1128
let height = info
1114
1129
. get ( "height" )
1115
1130
. and_then ( |t| t. as_u64 ( ) )
1131
+ . and_then ( |h| u32:: try_from ( h) . ok ( ) )
1116
1132
. ok_or_else ( || anyhow ! ( "Could not retrieve block height" ) ) ?;
1117
1133
1118
1134
let tip = chain_state. tip . read ( ) . expect ( "read meta" ) . clone ( ) ;
1119
- if height > tip. height as u64 {
1135
+ if height > tip. height {
1120
1136
return Err ( anyhow ! (
1121
1137
"Spaces is syncing at height {}, requested block height {}" ,
1122
1138
tip. height,
1123
1139
height
1124
1140
) ) ;
1125
1141
}
1126
- Ok ( None )
1142
+ Ok ( BlockMetaWithHash {
1143
+ hash,
1144
+ block_meta : BlockMeta {
1145
+ height,
1146
+ tx_meta : Vec :: new ( ) ,
1147
+ } ,
1148
+ } )
1127
1149
}
1128
1150
1129
1151
pub async fn handle_command (
@@ -1171,10 +1193,18 @@ impl AsyncChainState {
1171
1193
. context ( "could not fetch spaceout" ) ;
1172
1194
let _ = resp. send ( result) ;
1173
1195
}
1174
- ChainStateCommand :: GetBlockMeta { block_hash, resp } => {
1175
- let res =
1176
- Self :: get_indexed_block ( block_index, & block_hash, client, rpc, chain_state)
1177
- . await ;
1196
+ ChainStateCommand :: GetBlockMeta {
1197
+ height_or_hash,
1198
+ resp,
1199
+ } => {
1200
+ let res = Self :: get_indexed_block (
1201
+ block_index,
1202
+ height_or_hash,
1203
+ client,
1204
+ rpc,
1205
+ chain_state,
1206
+ )
1207
+ . await ;
1178
1208
let _ = resp. send ( res) ;
1179
1209
}
1180
1210
ChainStateCommand :: GetTxMeta { txid, resp } => {
@@ -1482,10 +1512,16 @@ impl AsyncChainState {
1482
1512
resp_rx. await ?
1483
1513
}
1484
1514
1485
- pub async fn get_block_meta ( & self , block_hash : BlockHash ) -> anyhow:: Result < Option < BlockMeta > > {
1515
+ pub async fn get_block_meta (
1516
+ & self ,
1517
+ height_or_hash : HeightOrHash ,
1518
+ ) -> anyhow:: Result < BlockMetaWithHash > {
1486
1519
let ( resp, resp_rx) = oneshot:: channel ( ) ;
1487
1520
self . sender
1488
- . send ( ChainStateCommand :: GetBlockMeta { block_hash, resp } )
1521
+ . send ( ChainStateCommand :: GetBlockMeta {
1522
+ height_or_hash,
1523
+ resp,
1524
+ } )
1489
1525
. await ?;
1490
1526
resp_rx. await ?
1491
1527
}
0 commit comments