@@ -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 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
+
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
+ block_identifier : BlockIdentifier ,
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
+ block_identifier : BlockIdentifier ,
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 > ;
@@ -599,19 +613,6 @@ impl WalletManager {
599
613
Ok ( ( ) )
600
614
}
601
615
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
-
615
616
async fn get_wallet_start_block ( & self , client : & reqwest:: Client ) -> anyhow:: Result < BlockId > {
616
617
let count: i32 = self
617
618
. rpc
@@ -797,11 +798,11 @@ impl RpcServer for RpcServerImpl {
797
798
798
799
async fn get_block_meta (
799
800
& self ,
800
- block_hash : BlockHash ,
801
- ) -> Result < Option < BlockMeta > , ErrorObjectOwned > {
801
+ block_identifier : BlockIdentifier ,
802
+ ) -> Result < BlockMetaWithHash , ErrorObjectOwned > {
802
803
let data = self
803
804
. store
804
- . get_block_meta ( block_hash )
805
+ . get_block_meta ( block_identifier )
805
806
. await
806
807
. map_err ( |error| ErrorObjectOwned :: owned ( -1 , error. to_string ( ) , None :: < String > ) ) ?;
807
808
@@ -1072,55 +1073,74 @@ impl AsyncChainState {
1072
1073
BlockHash :: from_str ( info. get ( "blockhash" ) . and_then ( |t| t. as_str ( ) ) . ok_or_else (
1073
1074
|| anyhow ! ( "Could not retrieve block hash for tx (is it in the mempool?)" ) ,
1074
1075
) ?) ?;
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 ?;
1076
1084
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) )
1084
1089
}
1085
1090
1086
1091
async fn get_indexed_block (
1087
1092
index : & mut Option < LiveSnapshot > ,
1088
- block_hash : & BlockHash ,
1093
+ block_identifier : BlockIdentifier ,
1089
1094
client : & reqwest:: Client ,
1090
1095
rpc : & BitcoinRpc ,
1091
1096
chain_state : & mut LiveSnapshot ,
1092
- ) -> Result < Option < BlockMeta > , anyhow:: Error > {
1097
+ ) -> Result < BlockMetaWithHash , anyhow:: Error > {
1093
1098
let index = index
1094
1099
. as_mut ( )
1095
1100
. 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
+ } ;
1100
1108
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
+ } ) ;
1103
1118
}
1104
1119
1105
1120
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 ) )
1107
1122
. await
1108
1123
. map_err ( |e| anyhow ! ( "Could not retrieve block ({})" , e) ) ?;
1109
1124
1110
1125
let height = info
1111
1126
. get ( "height" )
1112
1127
. and_then ( |t| t. as_u64 ( ) )
1128
+ . and_then ( |h| u32:: try_from ( h) . ok ( ) )
1113
1129
. ok_or_else ( || anyhow ! ( "Could not retrieve block height" ) ) ?;
1114
1130
1115
1131
let tip = chain_state. tip . read ( ) . expect ( "read meta" ) . clone ( ) ;
1116
- if height > tip. height as u64 {
1132
+ if height > tip. height {
1117
1133
return Err ( anyhow ! (
1118
1134
"Spaces is syncing at height {}, requested block height {}" ,
1119
1135
tip. height,
1120
1136
height
1121
1137
) ) ;
1122
1138
}
1123
- Ok ( None )
1139
+ Ok ( BlockMetaWithHash {
1140
+ hash,
1141
+ height,
1142
+ tx_meta : Vec :: new ( ) ,
1143
+ } )
1124
1144
}
1125
1145
1126
1146
pub async fn handle_command (
@@ -1168,10 +1188,18 @@ impl AsyncChainState {
1168
1188
. context ( "could not fetch spaceout" ) ;
1169
1189
let _ = resp. send ( result) ;
1170
1190
}
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 ;
1175
1203
let _ = resp. send ( res) ;
1176
1204
}
1177
1205
ChainStateCommand :: GetTxMeta { txid, resp } => {
@@ -1479,10 +1507,16 @@ impl AsyncChainState {
1479
1507
resp_rx. await ?
1480
1508
}
1481
1509
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 > {
1483
1514
let ( resp, resp_rx) = oneshot:: channel ( ) ;
1484
1515
self . sender
1485
- . send ( ChainStateCommand :: GetBlockMeta { block_hash, resp } )
1516
+ . send ( ChainStateCommand :: GetBlockMeta {
1517
+ block_identifier,
1518
+ resp,
1519
+ } )
1486
1520
. await ?;
1487
1521
resp_rx. await ?
1488
1522
}
0 commit comments