Removed mentions of use_latest_tip parameter, returning a NotFound http response if the chain tip can't be loaded for an rpc request

This commit is contained in:
Pavitthra Pandurangan
2021-12-01 16:55:36 -05:00
parent 713968e9d8
commit 7661d030c5
5 changed files with 102 additions and 138 deletions

View File

@@ -73,15 +73,8 @@ paths:
in: query
schema:
type: string
description: The Stacks chain tip to query from
- name: use_latest_tip
in: query
schema:
type: boolean
description: |
If use_latest_tip == true, the query will be run from the latest known tip (includes unconfirmed state).
If use_latest_tip == false or is unspecified, the tip is selected as usual (first checking value of the
tip parameter, otherwise taking the stacks chain tip).
description: The Stacks chain tip to query from. If tip == latest, the query will be run from the latest
known tip (includes unconfirmed state).
/v2/map_entry/{contract_address}/{contract_name}/{map_name}:
post:
summary: Get specific data-map inside a contract
@@ -133,15 +126,8 @@ paths:
in: query
schema:
type: string
description: The Stacks chain tip to query from
- name: use_latest_tip
in: query
schema:
type: boolean
description: |
If use_latest_tip == true, the query will be run from the latest known tip (includes unconfirmed state).
If use_latest_tip == false or is unspecified, the tip is selected as usual (first checking value of the
tip parameter, otherwise taking the stacks chain tip).
description: The Stacks chain tip to query from. If tip == latest, the query will be run from the latest
known tip (includes unconfirmed state).
x-codegen-request-body-name: key
requestBody:
description: Hex string serialization of the lookup key (which should be a Clarity value)
@@ -189,16 +175,9 @@ paths:
in: query
schema:
type: string
description: The Stacks chain tip to query from
description: The Stacks chain tip to query from. If tip == latest, the query will be run from the latest
known tip (includes unconfirmed state).
required: false
- name: use_latest_tip
in: query
schema:
type: boolean
description: |
If use_latest_tip == true, the query will be run from the latest known tip (includes unconfirmed state).
If use_latest_tip == false or is unspecified, the tip is selected as usual (first checking value of the
tip parameter, otherwise taking the stacks chain tip).
/v2/contracts/call-read/{contract_address}/{contract_name}/{function_name}:
post:
@@ -245,16 +224,9 @@ paths:
in: query
schema:
type: string
description: The Stacks chain tip to query from
description: The Stacks chain tip to query from. If tip == latest, the query will be run from the latest
known tip (includes unconfirmed state).
required: false
- name: use_latest_tip
in: query
schema:
type: boolean
description: |
If use_latest_tip == true, the query will be run from the latest known tip (includes unconfirmed state).
If use_latest_tip == false or is unspecified, the tip is selected as usual (first checking value of the
tip parameter, otherwise taking the stacks chain tip).
requestBody:
description: map of arguments and the simulated tx-sender where sender is either a Contract identifier or a normal Stacks address, and arguments is an array of hex serialized Clarity values.
required: true
@@ -296,15 +268,8 @@ paths:
in: query
schema:
type: string
description: The Stacks chain tip to query from
- name: use_latest_tip
in: query
schema:
type: boolean
description: |
If use_latest_tip == true, the query will be run from the latest known tip (includes unconfirmed state).
If use_latest_tip == false or is unspecified, the tip is selected as usual (first checking value of the
tip parameter, otherwise taking the stacks chain tip).
description: The Stacks chain tip to query from. If tip == latest, the query will be run from the latest
known tip (includes unconfirmed state).
responses:
200:
description: Success
@@ -460,15 +425,8 @@ paths:
in: query
schema:
type: string
description: The Stacks chain tip to query from
- name: use_latest_tip
in: query
schema:
type: boolean
description: |
If use_latest_tip == true, the query will be run from the latest known tip (includes unconfirmed state).
If use_latest_tip == false or is unspecified, the tip is selected as usual (first checking value of the
tip parameter, otherwise taking the stacks chain tip).
description: The Stacks chain tip to query from. If tip == latest, the query will be run from the latest
known tip (includes unconfirmed state).
/v2/traits/{contract_address}/{contract_name}/{trait_contract_address}/{trait_ contract_name}/{trait_name}:
get:

View File

@@ -383,6 +383,35 @@ impl UnconfirmedState {
0
}
}
/// Try returning the unconfirmed chain tip. Only return the tip if the underlying MARF trie
/// exists, otherwise return None.
pub fn get_unconfirmed_state_if_exists(&mut self) -> Result<Option<StacksBlockId>, String> {
if self.is_readable() {
let trie_exists = match self
.clarity_inst
.trie_exists_for_block(&self.unconfirmed_chain_tip)
{
Ok(res) => res,
Err(e) => {
let err_str = format!(
"Failed to load Stacks chain tip; error checking underlying trie: {}",
e
);
warn!("{}", err_str);
return Err(err_str);
}
};
if trie_exists {
Ok(Some(self.unconfirmed_chain_tip))
} else {
Ok(None)
}
} else {
Ok(None)
}
}
}
impl StacksChainState {

View File

@@ -2533,10 +2533,7 @@ impl HttpRequestType {
fn make_query_string(tip_req: &TipRequest, with_proof: bool) -> String {
match tip_req {
TipRequest::UseLatestUnconfirmedTip => {
format!(
"?use_latest_tip=true{}",
if with_proof { "" } else { "&proof=0" }
)
format!("?tip=latest{}", if with_proof { "" } else { "&proof=0" })
}
TipRequest::SpecificTip(tip) => {
format!("?tip={}{}", tip, if with_proof { "" } else { "&proof=0" })

View File

@@ -1555,31 +1555,13 @@ impl ConversationHttp {
TipRequest::UseLatestUnconfirmedTip => {
let unconfirmed_chain_tip_opt = match &mut chainstate.unconfirmed_state {
Some(unconfirmed_state) => {
if unconfirmed_state.is_readable() {
// Check if underlying MARF trie exists before returning unconfirmed chain tip
let trie_exists = match unconfirmed_state
.clarity_inst
.trie_exists_for_block(&unconfirmed_state.unconfirmed_chain_tip)
{
Ok(res) => res,
Err(e) => {
let response_metadata = HttpResponseMetadata::from(req);
warn!("Failed to load Stacks chain tip; error checking underlying trie");
let response = HttpResponseType::ServerError(
response_metadata,
format!("Failed to load Stacks chain tip: {:?}", e),
);
return response.send(http, fd).and_then(|_| Ok(None));
}
};
if trie_exists {
Some(unconfirmed_state.unconfirmed_chain_tip)
} else {
None
match unconfirmed_state.get_unconfirmed_state_if_exists() {
Ok(res) => res,
Err(msg) => {
let response_metadata = HttpResponseMetadata::from(req);
let response = HttpResponseType::NotFound(response_metadata, msg);
return response.send(http, fd).and_then(|_| Ok(None));
}
} else {
None
}
}
None => None,
@@ -1596,7 +1578,7 @@ impl ConversationHttp {
None => {
let response_metadata = HttpResponseMetadata::from(req);
warn!("Failed to load Stacks chain tip");
let response = HttpResponseType::ServerError(
let response = HttpResponseType::NotFound(
response_metadata,
format!("Failed to load Stacks chain tip"),
);
@@ -1629,7 +1611,6 @@ impl ConversationHttp {
fd: &mut W,
req: &HttpRequestType,
tip: StacksBlockId,
sortdb: &SortitionDB,
chainstate: &StacksChainState,
) -> Result<Option<(ConsensusHash, BlockHeaderHash)>, net_error> {
match chainstate.get_block_header_hashes(&tip)? {
@@ -2344,7 +2325,6 @@ impl ConversationHttp {
&mut reply,
&req,
tip,
sortdb,
chainstate,
)?
{
@@ -3539,9 +3519,9 @@ mod test {
#[test]
#[ignore]
fn test_rpc_getpoxinfo() {
/// Test v2/pox (aka GetPoxInfo) endpoint.
/// In this test, `tip_req` is set to UseLatestAnchoredTip.
/// Thus, the query for pox info will be against the canonical Stacks tip, which we expect to succeed.
// Test v2/pox (aka GetPoxInfo) endpoint.
// In this test, `tip_req` is set to UseLatestAnchoredTip.
// Thus, the query for pox info will be against the canonical Stacks tip, which we expect to succeed.
let pox_server_info = RefCell::new(None);
test_rpc(
"test_rpc_getpoxinfo",
@@ -3592,9 +3572,9 @@ mod test {
#[test]
#[ignore]
fn test_rpc_getpoxinfo_use_latest_tip() {
/// Test v2/pox (aka GetPoxInfo) endpoint.
/// In this test, we set `tip_req` to UseLatestUnconfirmedTip, and we expect that querying for pox
/// info against the unconfirmed state will succeed.
// Test v2/pox (aka GetPoxInfo) endpoint.
// In this test, we set `tip_req` to UseLatestUnconfirmedTip, and we expect that querying for pox
// info against the unconfirmed state will succeed.
let pox_server_info = RefCell::new(None);
test_rpc(
"test_rpc_getpoxinfo_use_latest_tip",
@@ -4325,11 +4305,11 @@ mod test {
#[test]
#[ignore]
fn test_rpc_get_contract_src() {
/// Test v2/contracts/source (aka GetContractSrc) endpoint.
/// In this test, we don't set any tip parameters, and allow the endpoint to execute against
/// the canonical Stacks tip.
/// The contract source we are querying for exists in the anchored state, so we expect the
/// query to succeed.
// Test v2/contracts/source (aka GetContractSrc) endpoint.
// In this test, we don't set any tip parameters, and allow the endpoint to execute against
// the canonical Stacks tip.
// The contract source we are querying for exists in the anchored state, so we expect the
// query to succeed.
test_rpc(
"test_rpc_get_contract_src",
40090,
@@ -4368,11 +4348,11 @@ mod test {
#[test]
#[ignore]
fn test_rpc_get_contract_src_unconfirmed_with_canonical_tip() {
/// Test v2/contracts/source (aka GetContractSrc) endpoint.
/// In this test, we don't set any tip parameters, and allow the endpoint to execute against
/// the canonical Stacks tip.
/// The contract source we are querying for only exists in the unconfirmed state, so we
/// expect the query to fail.
// Test v2/contracts/source (aka GetContractSrc) endpoint.
// In this test, we don't set any tip parameters, and allow the endpoint to execute against
// the canonical Stacks tip.
// The contract source we are querying for only exists in the unconfirmed state, so we
// expect the query to fail.
test_rpc(
"test_rpc_get_contract_src_unconfirmed_with_canonical_tip",
40100,
@@ -4411,10 +4391,10 @@ mod test {
#[test]
#[ignore]
fn test_rpc_get_contract_src_with_unconfirmed_tip() {
/// Test v2/contracts/source (aka GetContractSrc) endpoint.
/// In this test, we set `tip_req` to be the unconfirmed chain tip.
/// The contract source we are querying for exists in the unconfirmed state, so we expect
/// the query to succeed.
// Test v2/contracts/source (aka GetContractSrc) endpoint.
// In this test, we set `tip_req` to be the unconfirmed chain tip.
// The contract source we are querying for exists in the unconfirmed state, so we expect
// the query to succeed.
test_rpc(
"test_rpc_get_contract_src_with_unconfirmed_tip",
40102,
@@ -4460,10 +4440,10 @@ mod test {
#[test]
#[ignore]
fn test_rpc_get_contract_src_use_latest_tip() {
/// Test v2/contracts/source (aka GetContractSrc) endpoint.
/// In this test, we set `tip_req` to UseLatestUnconfirmedTip.
/// The contract source we are querying for exists in the unconfirmed state, so we expect
/// the query to succeed.
// Test v2/contracts/source (aka GetContractSrc) endpoint.
// In this test, we set `tip_req` to UseLatestUnconfirmedTip.
// The contract source we are querying for exists in the unconfirmed state, so we expect
// the query to succeed.
test_rpc(
"test_rpc_get_contract_src_use_latest_tip",
40104,
@@ -4676,9 +4656,9 @@ mod test {
#[test]
#[ignore]
fn test_rpc_get_map_entry() {
/// Test v2/map_entry (aka GetMapEntry) endpoint.
/// In this test, we don't set any tip parameters, and we expect that querying for map data
/// against the canonical Stacks tip will succeed.
// Test v2/map_entry (aka GetMapEntry) endpoint.
// In this test, we don't set any tip parameters, and we expect that querying for map data
// against the canonical Stacks tip will succeed.
test_rpc(
"test_rpc_get_map_entry",
40130,
@@ -4733,9 +4713,9 @@ mod test {
#[test]
#[ignore]
fn test_rpc_get_map_entry_unconfirmed() {
/// Test v2/map_entry (aka GetMapEntry) endpoint.
/// In this test, we set `tip_req` to UseLatestUnconfirmedTip, and we expect that querying for map data
/// against the unconfirmed state will succeed.
// Test v2/map_entry (aka GetMapEntry) endpoint.
// In this test, we set `tip_req` to UseLatestUnconfirmedTip, and we expect that querying for map data
// against the unconfirmed state will succeed.
test_rpc(
"test_rpc_get_map_entry_unconfirmed",
40140,
@@ -4851,9 +4831,9 @@ mod test {
#[test]
#[ignore]
fn test_rpc_get_contract_abi() {
/// Test /v2/contracts/interface (aka GetContractABI) endpoint.
/// In this test, we don't set any tip parameters, and we expect that querying
/// against the canonical Stacks tip will succeed.
// Test /v2/contracts/interface (aka GetContractABI) endpoint.
// In this test, we don't set any tip parameters, and we expect that querying
// against the canonical Stacks tip will succeed.
test_rpc(
"test_rpc_get_contract_abi",
40150,
@@ -4891,9 +4871,9 @@ mod test {
#[test]
#[ignore]
fn test_rpc_get_contract_abi_unconfirmed() {
/// Test /v2/contracts/interface (aka GetContractABI) endpoint.
/// In this test, we set `tip_req` to UseLatestUnconfirmedTip, and we expect that querying
/// against the unconfirmed state will succeed.
// Test /v2/contracts/interface (aka GetContractABI) endpoint.
// In this test, we set `tip_req` to UseLatestUnconfirmedTip, and we expect that querying
// against the unconfirmed state will succeed.
test_rpc(
"test_rpc_get_contract_abi_unconfirmed",
40152,
@@ -4969,9 +4949,9 @@ mod test {
#[test]
#[ignore]
fn test_rpc_call_read_only() {
/// Test /v2/contracts/call-read (aka CallReadOnlyFunction) endpoint.
/// In this test, we don't set any tip parameters, and we expect that querying
/// against the canonical Stacks tip will succeed.
// Test /v2/contracts/call-read (aka CallReadOnlyFunction) endpoint.
// In this test, we don't set any tip parameters, and we expect that querying
// against the canonical Stacks tip will succeed.
test_rpc(
"test_rpc_call_read_only",
40170,
@@ -5017,9 +4997,9 @@ mod test {
#[test]
#[ignore]
fn test_rpc_call_read_only_use_latest_tip() {
/// Test /v2/contracts/call-read (aka CallReadOnlyFunction) endpoint.
/// In this test, we set `tip_req` to UseLatestUnconfirmedTip, and we expect that querying
/// against the unconfirmed state will succeed.
// Test /v2/contracts/call-read (aka CallReadOnlyFunction) endpoint.
// In this test, we set `tip_req` to UseLatestUnconfirmedTip, and we expect that querying
// against the unconfirmed state will succeed.
test_rpc(
"test_rpc_call_read_only_use_latest_tip",
40172,

View File

@@ -710,9 +710,9 @@ fn get_contract_src(
) -> Result<String, String> {
let client = reqwest::blocking::Client::new();
let query_string = if use_latest_tip {
"?use_latest_tip=true".to_string()
"?tip=latest".to_string()
} else {
"?use_latest_tip=false".to_string()
"".to_string()
};
let path = format!(
"{}/v2/contracts/source/{}/{}{}",
@@ -5883,16 +5883,16 @@ fn atlas_stress_integration_test() {
#[test]
#[ignore]
fn use_latest_tip_integration_test() {
// The purpose of this test is to check if the `use_latest_tip` query parameter is working
// The purpose of this test is to check if setting the query parameter `tip` to `latest` is working
// as expected. Multiple endpoints accept this parameter, and in this test, we are using the
// GetContractSrc method to test it.
//
// The following scenarios are tested here:
// - The caller passes use_latest_tip=0, and the canonical chain tip is used regardless of the
// - The caller does not specify the tip paramater, and the canonical chain tip is used regardless of the
// state of the unconfirmed microblock stream.
// - The caller passes use_latest_tip=1 with an existing unconfirmed microblock stream, and
// - The caller passes tip=latest with an existing unconfirmed microblock stream, and
// Clarity state from the unconfirmed microblock stream is successfully loaded.
// - The caller passes use_latest_tip=1 with an empty unconfirmed microblock stream, and
// - The caller passes tip=latest with an empty unconfirmed microblock stream, and
// Clarity state from the canonical chain tip is successfully loaded (i.e. you don't
// get a 404 even though the unconfirmed chain tip points to a nonexistent MARF trie).
//
@@ -6060,7 +6060,7 @@ fn use_latest_tip_integration_test() {
let microblock_events = test_observer::get_microblocks();
assert_eq!(microblock_events.len(), 1);
// Set use_latest_tip=0, and ask for the source of the contract we just defined in a microblock.
// Don't set the tip parameter, and ask for the source of the contract we just defined in a microblock.
// This should fail because the anchored tip would be unaware of this contract.
let err_opt = get_contract_src(
&http_origin,
@@ -6072,17 +6072,17 @@ fn use_latest_tip_integration_test() {
Ok(_) => {
panic!(
"Asking for the contract source off the anchored tip for a contract published \
only in unconfirmed state should panic."
only in unconfirmed state should error."
);
}
// Expect to get "NoSuchContract" because the function we are attempting to call is in a
// contract that only exists on unconfirmed state (and we set `use_unconfirmed_tip` to false).
// contract that only exists on unconfirmed state (and we did not set tip).
Err(err_str) => {
assert!(err_str.contains("No contract source data found"));
}
}
// Set use_latest_tip=1, and ask for the source of the contract defined in the microblock.
// Set tip=latest, and ask for the source of the contract defined in the microblock.
// This should succeeed.
assert!(get_contract_src(
&http_origin,
@@ -6109,7 +6109,7 @@ fn use_latest_tip_integration_test() {
};
assert!(!trie_exists);
// Set use_latest_tip=1, and ask for the source of the contract defined in the previous epoch.
// Set tip=latest, and ask for the source of the contract defined in the previous epoch.
// The underlying MARF trie for the unconfirmed tip does not exist, so the transaction will be
// validated against the confirmed chain tip instead of the unconfirmed tip. This should be valid.
assert!(get_contract_src(