Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 3f0740f

Browse files
committedFeb 11, 2025·
getblockmeta: return hash
1 parent 5e7a7d1 commit 3f0740f

File tree

4 files changed

+141
-100
lines changed

4 files changed

+141
-100
lines changed
 

Diff for: ‎node/src/format.rs

+112-64
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
1+
use crate::rpc::ServerInfo;
2+
use crate::wallets::{ListSpacesResponse, TxInfo, TxResponse, WalletResponse};
13
use clap::ValueEnum;
24
use colored::{Color, Colorize};
35
use jsonrpsee::core::Serialize;
6+
use protocol::{
7+
bitcoin::{Amount, Network, OutPoint},
8+
Covenant,
9+
};
410
use serde::Deserialize;
511
use tabled::{Table, Tabled};
6-
use protocol::bitcoin::{Amount, Network, OutPoint};
7-
use protocol::{Covenant};
812
use wallet::address::SpaceAddress;
9-
use wallet::{Balance, DoubleUtxo, WalletInfo, WalletOutput};
1013
use wallet::bdk_wallet::KeychainKind;
1114
use wallet::bitcoin::{Address, Txid};
12-
use wallet::tx_event::{BidEventDetails, BidoutEventDetails, OpenEventDetails, SendEventDetails, TransferEventDetails, TxEventKind};
13-
use crate::rpc::ServerInfo;
14-
use crate::wallets::{ListSpacesResponse, TxInfo, TxResponse, WalletResponse};
15+
use wallet::tx_event::{
16+
BidEventDetails, BidoutEventDetails, OpenEventDetails, SendEventDetails, TransferEventDetails,
17+
TxEventKind,
18+
};
19+
use wallet::{Balance, DoubleUtxo, WalletInfo, WalletOutput};
1520

1621
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, ValueEnum, Serialize, Deserialize)]
1722
#[serde(rename_all = "lowercase")]
@@ -56,7 +61,7 @@ struct RegisteredSpaces {
5661
#[tabled(rename = "DAYS LEFT")]
5762
days_left: String,
5863
#[tabled(rename = "UTXO")]
59-
utxo: OutPoint
64+
utxo: OutPoint,
6065
}
6166

6267
#[derive(Tabled)]
@@ -91,17 +96,19 @@ fn format_days_left(current_block: u32, claim_height: Option<u32>) -> String {
9196
pub fn print_list_bidouts(bidouts: Vec<DoubleUtxo>, format: Format) {
9297
match format {
9398
Format::Text => {
94-
let all : Vec<_> = bidouts.into_iter().map(|out| Bidout {
95-
txid: out.spend.outpoint.txid,
96-
vout_1: out.spend.outpoint.vout,
97-
vout_2: out.auction.outpoint.vout,
98-
confirmed: out.confirmed,
99-
}).collect();
99+
let all: Vec<_> = bidouts
100+
.into_iter()
101+
.map(|out| Bidout {
102+
txid: out.spend.outpoint.txid,
103+
vout_1: out.spend.outpoint.vout,
104+
vout_2: out.auction.outpoint.vout,
105+
confirmed: out.confirmed,
106+
})
107+
.collect();
100108
println!("{}", ascii_table(all));
101109
}
102110
Format::Json => {
103111
println!("{}", serde_json::to_string_pretty(&bidouts).unwrap());
104-
105112
}
106113
}
107114
}
@@ -117,17 +124,18 @@ pub fn print_list_transactions(txs: Vec<TxInfo>, format: Format) {
117124
}
118125
}
119126

120-
121-
122127
pub fn print_list_unspent(utxos: Vec<WalletOutput>, format: Format) {
123128
match format {
124129
Format::Text => {
125-
let utxos : Vec<_> = utxos.iter().map(|utxo| UnspentOutput {
126-
outpoint: utxo.output.outpoint,
127-
confirmed: utxo.output.chain_position.is_confirmed(),
128-
value: utxo.output.txout.value,
129-
external: utxo.output.keychain == KeychainKind::External,
130-
}).collect();
130+
let utxos: Vec<_> = utxos
131+
.iter()
132+
.map(|utxo| UnspentOutput {
133+
outpoint: utxo.output.outpoint,
134+
confirmed: utxo.output.chain_position.is_confirmed(),
135+
value: utxo.output.txout.value,
136+
external: utxo.output.keychain == KeychainKind::External,
137+
})
138+
.collect();
131139
println!("{}", ascii_table(utxos))
132140
}
133141
Format::Json => {
@@ -153,10 +161,7 @@ pub fn print_wallet_info(info: WalletInfo, format: Format) {
153161
match format {
154162
Format::Text => {
155163
println!("WALLET: {}", info.label);
156-
println!(" Tip {}\n Birthday {}",
157-
info.tip,
158-
info.start_block
159-
);
164+
println!(" Tip {}\n Birthday {}", info.tip, info.start_block);
160165

161166
println!(" Public descriptors");
162167
for desc in info.descriptors {
@@ -184,9 +189,18 @@ pub fn print_wallet_balance_response(balance: Balance, format: Format) {
184189
match format {
185190
Format::Text => {
186191
println!("Balance: {}", balance.balance.to_sat());
187-
println!(" Confirmed {:>14}", balance.details.balance.confirmed.to_sat());
188-
println!(" Trusted pending {:>14}", balance.details.balance.trusted_pending.to_sat());
189-
println!(" Untrusted pending {:>14}", balance.details.balance.untrusted_pending.to_sat());
192+
println!(
193+
" Confirmed {:>14}",
194+
balance.details.balance.confirmed.to_sat()
195+
);
196+
println!(
197+
" Trusted pending {:>14}",
198+
balance.details.balance.trusted_pending.to_sat()
199+
);
200+
println!(
201+
" Untrusted pending {:>14}",
202+
balance.details.balance.untrusted_pending.to_sat()
203+
);
190204
println!(" Dust & in-auction {:>14}", balance.details.dust.to_sat());
191205
}
192206
Format::Json => {
@@ -195,7 +209,11 @@ pub fn print_wallet_balance_response(balance: Balance, format: Format) {
195209
}
196210
}
197211

198-
pub fn print_list_spaces_response(current_block: u32, response: ListSpacesResponse, format: Format) {
212+
pub fn print_list_spaces_response(
213+
current_block: u32,
214+
response: ListSpacesResponse,
215+
format: Format,
216+
) {
199217
match format {
200218
Format::Text => {
201219
let mut outbids = Vec::new();
@@ -209,7 +227,11 @@ pub fn print_list_spaces_response(current_block: u32, response: ListSpacesRespon
209227
days_left: "".to_string(),
210228
};
211229
match space.covenant {
212-
Covenant::Bid { total_burned, claim_height, .. } => {
230+
Covenant::Bid {
231+
total_burned,
232+
claim_height,
233+
..
234+
} => {
213235
outbid.last_confirmed_bid = total_burned.to_sat();
214236
outbid.days_left = format_days_left(current_block, claim_height);
215237
}
@@ -227,9 +249,15 @@ pub fn print_list_spaces_response(current_block: u32, response: ListSpacesRespon
227249
claim_at: "--".to_string(),
228250
};
229251
match space.covenant {
230-
Covenant::Bid { total_burned, claim_height, .. } => {
252+
Covenant::Bid {
253+
total_burned,
254+
claim_height,
255+
..
256+
} => {
231257
winning.bid = total_burned.to_sat();
232-
winning.claim_at = claim_height.map(|h| h.to_string()).unwrap_or("--".to_string());
258+
winning.claim_at = claim_height
259+
.map(|h| h.to_string())
260+
.unwrap_or("--".to_string());
233261
winning.days_left = format_days_left(current_block, claim_height);
234262
if winning.days_left == "0.00" {
235263
winning.days_left = "Ready to claim".to_string();
@@ -250,28 +278,36 @@ pub fn print_list_spaces_response(current_block: u32, response: ListSpacesRespon
250278
match &space.covenant {
251279
Covenant::Transfer { expire_height, .. } => {
252280
registered.expire_at = *expire_height as _;
253-
registered.days_left = format_days_left(current_block, Some(*expire_height));
281+
registered.days_left =
282+
format_days_left(current_block, Some(*expire_height));
254283
}
255284
_ => {}
256285
}
257286
owned.push(registered);
258287
}
259288

260-
261289
if !outbids.is_empty() {
262290
println!("⚠️ OUTBID ({} spaces): ", outbids.len().to_string().bold());
263291
let table = ascii_table(outbids);
264292
println!("{}", table);
265293
}
266294

267295
if !winnings.is_empty() {
268-
println!("{} WINNING ({} spaces):","✓".color(Color::Green), winnings.len().to_string().bold());
296+
println!(
297+
"{} WINNING ({} spaces):",
298+
"✓".color(Color::Green),
299+
winnings.len().to_string().bold()
300+
);
269301
let table = ascii_table(winnings);
270302
println!("{}", table);
271303
}
272304

273305
if !owned.is_empty() {
274-
println!("{} ({} spaces): ", "🔑 OWNED", owned.len().to_string().bold());
306+
println!(
307+
"{} ({} spaces): ",
308+
"🔑 OWNED",
309+
owned.len().to_string().bold()
310+
);
275311
let table = ascii_table(owned);
276312
println!("{}", table);
277313
}
@@ -292,13 +328,19 @@ pub fn print_wallet_response_text(network: Network, response: WalletResponse) {
292328

293329
for tx in response.result {
294330
if tx.events.iter().any(|event| match event.kind {
295-
TxEventKind::Open | TxEventKind::Bid | TxEventKind::Register |
296-
TxEventKind::Transfer | TxEventKind::Send | TxEventKind::Renew | TxEventKind::Buy
297-
=> true,
331+
TxEventKind::Open
332+
| TxEventKind::Bid
333+
| TxEventKind::Register
334+
| TxEventKind::Transfer
335+
| TxEventKind::Send
336+
| TxEventKind::Renew
337+
| TxEventKind::Buy => true,
298338
_ => false,
299339
}) {
300340
main_txs.push(tx);
301-
} else { secondary_txs.push(tx); }
341+
} else {
342+
secondary_txs.push(tx);
343+
}
302344
}
303345

304346
for tx in main_txs {
@@ -328,7 +370,7 @@ pub fn print_error_rpc_response(code: i32, message: String, format: Format) {
328370
fn print_tx_response(network: Network, response: TxResponse) {
329371
match response.error {
330372
None => {
331-
println!("{} Transaction {}","✓".color(Color::Green), response.txid);
373+
println!("{} Transaction {}", "✓".color(Color::Green), response.txid);
332374
}
333375
Some(errors) => {
334376
println!("⚠️ Transaction failed to broadcast");
@@ -341,51 +383,57 @@ fn print_tx_response(network: Network, response: TxResponse) {
341383
}
342384

343385
for event in response.events {
344-
println!(" - {} {}", capitalize(event.kind.to_string()), event.space.unwrap_or("".to_string()));
386+
println!(
387+
" - {} {}",
388+
capitalize(event.kind.to_string()),
389+
event.space.unwrap_or("".to_string())
390+
);
345391

346392
match event.kind {
347393
TxEventKind::Open => {
348-
let open_details: OpenEventDetails = serde_json::from_value(
349-
event.details.expect("details"))
350-
.expect("deserialize open event");
394+
let open_details: OpenEventDetails =
395+
serde_json::from_value(event.details.expect("details"))
396+
.expect("deserialize open event");
351397

352398
println!(" Initial bid: {}", open_details.initial_bid.to_sat());
353399
}
354400
TxEventKind::Bid => {
355-
let bid_details: BidEventDetails = serde_json::from_value(
356-
event.details.expect("details"))
357-
.expect("deserialize bid event");
358-
println!(" New bid: {} (previous {})",
359-
bid_details.current_bid.to_sat(),
360-
bid_details.previous_bid.to_sat()
401+
let bid_details: BidEventDetails =
402+
serde_json::from_value(event.details.expect("details"))
403+
.expect("deserialize bid event");
404+
println!(
405+
" New bid: {} (previous {})",
406+
bid_details.current_bid.to_sat(),
407+
bid_details.previous_bid.to_sat()
361408
);
362409
}
363410
TxEventKind::Send => {
364-
let send_details: SendEventDetails = serde_json::from_value(
365-
event.details.expect("details"))
366-
.expect("deserialize send event");
411+
let send_details: SendEventDetails =
412+
serde_json::from_value(event.details.expect("details"))
413+
.expect("deserialize send event");
367414

368-
let addr = Address::from_script(send_details.recipient_script_pubkey.as_script(), network)
369-
.expect("valid address");
415+
let addr =
416+
Address::from_script(send_details.recipient_script_pubkey.as_script(), network)
417+
.expect("valid address");
370418

371419
println!(" Amount: {}", send_details.amount.to_sat());
372420
println!(" Recipient: {}", addr);
373421
}
374422
TxEventKind::Transfer => {
375-
let transfer_details: TransferEventDetails = serde_json::from_value(
376-
event.details.expect("details"))
377-
.expect("deserialize transfer event");
423+
let transfer_details: TransferEventDetails =
424+
serde_json::from_value(event.details.expect("details"))
425+
.expect("deserialize transfer event");
378426

379427
let addr = SpaceAddress(
380428
Address::from_script(transfer_details.script_pubkey.as_script(), network)
381-
.expect("valid address")
429+
.expect("valid address"),
382430
);
383431
println!(" Recipient: {}", addr);
384432
}
385433
TxEventKind::Bidout => {
386-
let bidout: BidoutEventDetails = serde_json::from_value(
387-
event.details.expect("details"))
388-
.expect("deserialize bidout event");
434+
let bidout: BidoutEventDetails =
435+
serde_json::from_value(event.details.expect("details"))
436+
.expect("deserialize bidout event");
389437
println!(" Count: {}", bidout.count);
390438
}
391439
_ => {}

Diff for: ‎node/src/node.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: ‎node/src/rpc.rs

+26-33
Original file line numberDiff line numberDiff line change
@@ -67,29 +67,18 @@ pub struct SignedMessage {
6767
pub signature: secp256k1::schnorr::Signature,
6868
}
6969

70-
#[derive(Debug, Serialize)]
70+
#[derive(Debug, Clone, Serialize, Deserialize)]
71+
#[serde(untagged)]
7172
pub enum BlockIdentifier {
7273
Hash(BlockHash),
7374
Height(u32),
7475
}
75-
impl<'de> Deserialize<'de> for BlockIdentifier {
76-
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
77-
where
78-
D: serde::Deserializer<'de>,
79-
{
80-
#[derive(Deserialize)]
81-
#[serde(untagged)]
82-
enum RawIdentifier {
83-
String(String),
84-
Number(u32),
85-
}
86-
match RawIdentifier::deserialize(deserializer)? {
87-
RawIdentifier::String(s) => BlockHash::from_str(&s)
88-
.map(BlockIdentifier::Hash)
89-
.map_err(serde::de::Error::custom),
90-
RawIdentifier::Number(n) => Ok(BlockIdentifier::Height(n)),
91-
}
92-
}
76+
77+
#[derive(Debug, Clone, Serialize, Deserialize)]
78+
pub struct BlockMetaWithHash {
79+
pub hash: BlockHash,
80+
pub height: u32,
81+
pub tx_meta: Vec<TxEntry>,
9382
}
9483

9584
pub enum ChainStateCommand {
@@ -119,7 +108,7 @@ pub enum ChainStateCommand {
119108
},
120109
GetBlockMeta {
121110
block_identifier: BlockIdentifier,
122-
resp: Responder<anyhow::Result<BlockMeta>>,
111+
resp: Responder<anyhow::Result<BlockMetaWithHash>>,
123112
},
124113
EstimateBid {
125114
target: usize,
@@ -180,7 +169,7 @@ pub trait Rpc {
180169
async fn get_block_meta(
181170
&self,
182171
block_identifier: BlockIdentifier,
183-
) -> Result<BlockMeta, ErrorObjectOwned>;
172+
) -> Result<BlockMetaWithHash, ErrorObjectOwned>;
184173

185174
#[method(name = "gettxmeta")]
186175
async fn get_tx_meta(&self, txid: Txid) -> Result<Option<TxEntry>, ErrorObjectOwned>;
@@ -716,7 +705,7 @@ impl RpcServer for RpcServerImpl {
716705
async fn get_block_meta(
717706
&self,
718707
block_identifier: BlockIdentifier,
719-
) -> Result<BlockMeta, ErrorObjectOwned> {
708+
) -> Result<BlockMetaWithHash, ErrorObjectOwned> {
720709
let data = self
721710
.store
722711
.get_block_meta(block_identifier)
@@ -979,28 +968,31 @@ impl AsyncChainState {
979968
client: &reqwest::Client,
980969
rpc: &BitcoinRpc,
981970
chain_state: &mut LiveSnapshot,
982-
) -> Result<BlockMeta, anyhow::Error> {
971+
) -> Result<BlockMetaWithHash, anyhow::Error> {
983972
let index = index
984973
.as_mut()
985974
.ok_or_else(|| anyhow!("block index must be enabled"))?;
986-
let block_hash = match block_identifier {
975+
let hash = match block_identifier {
987976
BlockIdentifier::Hash(hash) => hash,
988977
BlockIdentifier::Height(height) => rpc
989978
.send_json(client, &rpc.get_block_hash(height))
990979
.await
991980
.map_err(|e| anyhow!("Could not retrieve block hash ({})", e))?,
992981
};
993-
let hash = BaseHash::from_slice(block_hash.as_ref());
994-
let block: Option<BlockMeta> = index
995-
.get(hash)
996-
.context("Could not fetch block from index")?;
997982

998-
if let Some(block_set) = block {
999-
return Ok(block_set);
983+
if let Some(BlockMeta { height, tx_meta }) = index
984+
.get(BaseHash::from_slice(hash.as_ref()))
985+
.context("Could not fetch block from index")?
986+
{
987+
return Ok(BlockMetaWithHash {
988+
hash,
989+
height,
990+
tx_meta,
991+
});
1000992
}
1001993

1002994
let info: serde_json::Value = rpc
1003-
.send_json(client, &rpc.get_block_header(&block_hash))
995+
.send_json(client, &rpc.get_block_header(&hash))
1004996
.await
1005997
.map_err(|e| anyhow!("Could not retrieve block ({})", e))?;
1006998

@@ -1018,7 +1010,8 @@ impl AsyncChainState {
10181010
height
10191011
));
10201012
}
1021-
Ok(BlockMeta {
1013+
Ok(BlockMetaWithHash {
1014+
hash,
10221015
height,
10231016
tx_meta: Vec::new(),
10241017
})
@@ -1211,7 +1204,7 @@ impl AsyncChainState {
12111204
pub async fn get_block_meta(
12121205
&self,
12131206
block_identifier: BlockIdentifier,
1214-
) -> anyhow::Result<BlockMeta> {
1207+
) -> anyhow::Result<BlockMetaWithHash> {
12151208
let (resp, resp_rx) = oneshot::channel();
12161209
self.sender
12171210
.send(ChainStateCommand::GetBlockMeta {

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)
Please sign in to comment.