Skip to content

Commit

Permalink
Only accept sat number in recursive endpoint (#2732)
Browse files Browse the repository at this point in the history
  • Loading branch information
raphjaph authored Nov 23, 2023
1 parent 61fbdbd commit 99b944d
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 164 deletions.
117 changes: 110 additions & 7 deletions src/subcommand/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,15 @@ impl Server {
.route("/r/blockheight", get(Self::block_height))
.route("/r/blocktime", get(Self::block_time))
.route("/r/metadata/:inscription_id", get(Self::metadata))
.route("/r/sat/:sat", get(Self::sat_inscriptions))
.route("/r/sat/:sat/:page", get(Self::sat_inscriptions_paginated))
.route("/r/sat/:sat/at/:index", get(Self::sat_inscription_at_index))
.route("/r/sat/:sat_number", get(Self::sat_inscriptions))
.route(
"/r/sat/:sat_number/:page",
get(Self::sat_inscriptions_paginated),
)
.route(
"/r/sat/:sat_number/at/:index",
get(Self::sat_inscription_at_index),
)
.route("/range/:start/:end", get(Self::range))
.route("/rare.txt", get(Self::rare_txt))
.route("/rune/:rune", get(Self::rune))
Expand Down Expand Up @@ -1447,22 +1453,22 @@ impl Server {

async fn sat_inscriptions(
Extension(index): Extension<Arc<Index>>,
Path(DeserializeFromStr(sat)): Path<DeserializeFromStr<Sat>>,
Path(sat): Path<u64>,
) -> ServerResult<Json<SatInscriptionsJson>> {
Self::sat_inscriptions_paginated(Extension(index), Path((DeserializeFromStr(sat), 0))).await
Self::sat_inscriptions_paginated(Extension(index), Path((sat, 0))).await
}

async fn sat_inscriptions_paginated(
Extension(index): Extension<Arc<Index>>,
Path((DeserializeFromStr(sat), page)): Path<(DeserializeFromStr<Sat>, u64)>,
Path((sat, page)): Path<(u64, u64)>,
) -> ServerResult<Json<SatInscriptionsJson>> {
if !index.has_sat_index() {
return Err(ServerError::NotFound(
"this server has no sat index".to_string(),
));
}

let (ids, more) = index.get_inscription_ids_by_sat_paginated(sat, 100, page)?;
let (ids, more) = index.get_inscription_ids_by_sat_paginated(Sat(sat), 100, page)?;

Ok(Json(SatInscriptionsJson { ids, more, page }))
}
Expand Down Expand Up @@ -4393,4 +4399,101 @@ next
),
);
}

#[test]
fn sat_recursive_endpoints() {
let server = TestServer::new_with_regtest_with_index_sats();

assert_eq!(
server.get_json::<SatInscriptionsJson>("/r/sat/5000000000"),
SatInscriptionsJson {
ids: vec![],
page: 0,
more: false
}
);

assert_eq!(
server.get_json::<SatInscriptionJson>("/r/sat/5000000000/at/0"),
SatInscriptionJson { id: None }
);

server.mine_blocks(1);

let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate {
inputs: &[(1, 0, 0, inscription("text/plain", "foo").to_witness())],
..Default::default()
});

server.mine_blocks(1);

let mut ids = Vec::new();
ids.push(InscriptionId { txid, index: 0 });

for i in 1..111 {
let txid = server.bitcoin_rpc_server.broadcast_tx(TransactionTemplate {
inputs: &[(i + 1, 1, 0, inscription("text/plain", "foo").to_witness())],
..Default::default()
});

server.mine_blocks(1);

ids.push(InscriptionId { txid, index: 0 });
}

let paginated_response = server.get_json::<SatInscriptionsJson>("/r/sat/5000000000");

let equivalent_paginated_response =
server.get_json::<SatInscriptionsJson>("/r/sat/5000000000/0");

assert_eq!(paginated_response.ids.len(), 100);
assert!(paginated_response.more);
assert_eq!(paginated_response.page, 0);

assert_eq!(
paginated_response.ids.len(),
equivalent_paginated_response.ids.len()
);
assert_eq!(paginated_response.more, equivalent_paginated_response.more);
assert_eq!(paginated_response.page, equivalent_paginated_response.page);

let paginated_response = server.get_json::<SatInscriptionsJson>("/r/sat/5000000000/1");

assert_eq!(paginated_response.ids.len(), 11);
assert!(!paginated_response.more);
assert_eq!(paginated_response.page, 1);

assert_eq!(
server
.get_json::<SatInscriptionJson>("/r/sat/5000000000/at/0")
.id,
Some(ids[0])
);

assert_eq!(
server
.get_json::<SatInscriptionJson>("/r/sat/5000000000/at/-111")
.id,
Some(ids[0])
);

assert_eq!(
server
.get_json::<SatInscriptionJson>("/r/sat/5000000000/at/110")
.id,
Some(ids[110])
);

assert_eq!(
server
.get_json::<SatInscriptionJson>("/r/sat/5000000000/at/-1")
.id,
Some(ids[110])
);

assert!(server
.get_json::<SatInscriptionJson>("/r/sat/5000000000/at/111")
.id
.is_none());
}
}
38 changes: 2 additions & 36 deletions tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,8 @@ use {
inscription_id::InscriptionId,
rarity::Rarity,
templates::{
block::BlockJson,
inscription::InscriptionJson,
inscriptions::InscriptionsJson,
output::OutputJson,
sat::{SatInscriptionJson, SatInscriptionsJson, SatJson},
block::BlockJson, inscription::InscriptionJson, inscriptions::InscriptionsJson,
output::OutputJson, sat::SatJson,
},
SatPoint,
},
Expand Down Expand Up @@ -70,37 +67,6 @@ fn inscribe(rpc_server: &test_bitcoincore_rpc::Handle) -> (InscriptionId, Txid)
(output.inscriptions[0].id, output.reveal)
}

fn reinscribe(rpc_server: &test_bitcoincore_rpc::Handle, n: usize) -> Vec<InscriptionId> {
let mut inscriptions = Vec::new();

let mut output = CommandBuilder::new("wallet inscribe --fee-rate 1 --file foo.txt")
.write("foo.txt", "FOO")
.rpc_server(rpc_server)
.run_and_deserialize_output::<Inscribe>();

inscriptions.push(output.inscriptions[0].id);

rpc_server.mine_blocks(1);

for _ in 1..n {
output = CommandBuilder::new(format!(
"wallet inscribe --reinscribe --satpoint {} --fee-rate 1 --file foo.txt",
output.inscriptions[0].location
))
.write("foo.txt", "FOO")
.rpc_server(rpc_server)
.run_and_deserialize_output::<Inscribe>();

inscriptions.push(output.inscriptions[0].id);

rpc_server.mine_blocks(1);
}

assert_eq!(inscriptions.len(), n);

inscriptions
}

fn envelope(payload: &[&[u8]]) -> bitcoin::Witness {
let mut builder = bitcoin::script::Builder::new()
.push_opcode(bitcoin::opcodes::OP_FALSE)
Expand Down
121 changes: 0 additions & 121 deletions tests/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,127 +410,6 @@ fn all_endpoints_in_recursive_directory_return_json() {
assert!(server.request("/blockhash/2").json::<String>().is_err());
}

#[test]
#[ignore]
fn sat_recursive_endpoints() {
let rpc_server = test_bitcoincore_rpc::spawn();

create_wallet(&rpc_server);

rpc_server.mine_blocks(1);

let server = TestServer::spawn_with_args(&rpc_server, &["--index-sats"]);

assert_eq!(
server
.request("/r/sat/nvtcsezkbth")
.json::<SatInscriptionsJson>()
.unwrap(),
SatInscriptionsJson {
ids: vec![],
page: 0,
more: false
}
);

assert_eq!(
server
.request("/r/sat/5000000000")
.json::<SatInscriptionsJson>()
.unwrap(),
SatInscriptionsJson {
ids: vec![],
page: 0,
more: false
}
);

assert_eq!(
server
.request("/r/sat/5000000000/at/0")
.json::<SatInscriptionJson>()
.unwrap(),
SatInscriptionJson { id: None }
);

let inscriptions = reinscribe(&rpc_server, 111);

let server = TestServer::spawn_with_args(&rpc_server, &["--index-sats"]);

let paginated_response = server
.request("/r/sat/5000000000")
.json::<SatInscriptionsJson>()
.unwrap();

let equivalent_paginated_response = server
.request("/r/sat/nvtcsezkbth/0")
.json::<SatInscriptionsJson>()
.unwrap();

assert_eq!(paginated_response.ids.len(), 100);
assert!(paginated_response.more);
assert_eq!(paginated_response.page, 0);

assert_eq!(
paginated_response.ids.len(),
equivalent_paginated_response.ids.len()
);
assert_eq!(paginated_response.more, equivalent_paginated_response.more);
assert_eq!(paginated_response.page, equivalent_paginated_response.page);

let paginated_response = server
.request("/r/sat/5000000000/1")
.json::<SatInscriptionsJson>()
.unwrap();

assert_eq!(paginated_response.ids.len(), 11);
assert!(!paginated_response.more);
assert_eq!(paginated_response.page, 1);

assert_eq!(
server
.request("/r/sat/nvtcsezkbth/at/0")
.json::<SatInscriptionJson>()
.unwrap()
.id,
Some(inscriptions[0])
);

assert_eq!(
server
.request("/r/sat/5000000000/at/-111")
.json::<SatInscriptionJson>()
.unwrap()
.id,
Some(inscriptions[0])
);

assert_eq!(
server
.request("/r/sat/5000000000/at/110")
.json::<SatInscriptionJson>()
.unwrap()
.id,
Some(inscriptions[110])
);

assert_eq!(
server
.request("/r/sat/0°1′1″0‴/at/-1")
.json::<SatInscriptionJson>()
.unwrap()
.id,
Some(inscriptions[110])
);

assert!(server
.request("/r/sat/5000000000/at/111")
.json::<SatInscriptionJson>()
.unwrap()
.id
.is_none());
}

#[test]
fn sat_recursive_endpoints_without_sat_index_return_404() {
let rpc_server = test_bitcoincore_rpc::spawn();
Expand Down

0 comments on commit 99b944d

Please sign in to comment.