Skip to content

Commit

Permalink
Merge pull request #2778 from blockstack/fix/rpc-tip
Browse files Browse the repository at this point in the history
Feat: added use_latest_tip query parameter to the relevant v2 endpoints
  • Loading branch information
pavitthrap authored Dec 21, 2021
2 parents 194a5b8 + dc34f9e commit 4fc1f28
Show file tree
Hide file tree
Showing 11 changed files with 1,134 additions and 302 deletions.
1 change: 1 addition & 0 deletions .github/workflows/bitcoin-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ jobs:
- tests::neon_integrations::filter_low_fee_tx_integration_test
- tests::neon_integrations::filter_long_runtime_tx_integration_test
- tests::neon_integrations::mining_transactions_is_fair
- tests::neon_integrations::use_latest_tip_integration_test
- tests::epoch_205::test_dynamic_db_method_costs
- tests::epoch_205::transition_empty_blocks
- tests::epoch_205::test_cost_limit_switch_version205
Expand Down
28 changes: 21 additions & 7 deletions docs/rpc/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ 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).
/v2/map_entry/{contract_address}/{contract_name}/{map_name}:
post:
summary: Get specific data-map inside a contract
Expand Down Expand Up @@ -126,7 +126,8 @@ 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).
x-codegen-request-body-name: key
requestBody:
description: Hex string serialization of the lookup key (which should be a Clarity value)
Expand Down Expand Up @@ -174,7 +175,8 @@ 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

/v2/contracts/call-read/{contract_address}/{contract_name}/{function_name}:
Expand Down Expand Up @@ -222,7 +224,8 @@ 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
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.
Expand Down Expand Up @@ -265,7 +268,8 @@ 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).
responses:
200:
description: Success
Expand Down Expand Up @@ -416,6 +420,13 @@ paths:
$ref: ./api/core-node/get-pox.schema.json
example:
$ref: ./api/core-node/get-pox.example.json
parameters:
- name: tip
in: query
schema:
type: string
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:
Expand Down Expand Up @@ -468,4 +479,7 @@ 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).
If the tip is left unspecified, the stacks chain tip will be selected (only includes confirmed state).
29 changes: 29 additions & 0 deletions src/chainstate/stacks/db/unconfirmed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
6 changes: 6 additions & 0 deletions src/clarity_vm/clarity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ use crate::types::chainstate::StacksBlockId;
use crate::types::chainstate::StacksMicroblockHeader;
use crate::types::proof::TrieHash;
use crate::util::boot::{boot_code_acc, boot_code_addr, boot_code_id, boot_code_tx_auth};
use crate::util::db::Error as db_error;
use crate::util::secp256k1::MessageSignature;
use types::chainstate::BurnchainHeaderHash;

Expand Down Expand Up @@ -517,6 +518,11 @@ impl ClarityInstance {
})
}

pub fn trie_exists_for_block(&mut self, bhh: &StacksBlockId) -> Result<bool, db_error> {
let mut datastore = self.datastore.begin_read_only(None);
datastore.trie_exists_for_block(bhh)
}

/// Evaluate program read-only at `at_block`. This will be evaluated in the Stacks epoch that
/// was active *during* the evaluation of `at_block`
pub fn eval_read_only(
Expand Down
8 changes: 8 additions & 0 deletions src/clarity_vm/database/marf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use vm::types::QualifiedContractIdentifier;
use crate::types::chainstate::{BlockHeaderHash, StacksBlockHeader};
use crate::types::chainstate::{MARFValue, StacksBlockId};
use crate::types::proof::{ClarityMarfTrieId, TrieHash, TrieMerkleProof};
use crate::util::db::Error as db_error;

/// The MarfedKV struct is used to wrap a MARF data structure and side-storage
/// for use as a K/V store for ClarityDB or the AnalysisDB.
Expand Down Expand Up @@ -267,6 +268,13 @@ impl<'a> ReadOnlyMarfStore<'a> {
pub fn as_analysis_db<'b>(&'b mut self) -> AnalysisDatabase<'b> {
AnalysisDatabase::new(self)
}

pub fn trie_exists_for_block(&mut self, bhh: &StacksBlockId) -> Result<bool, db_error> {
self.marf.with_conn(|conn| match conn.has_block(bhh) {
Ok(res) => Ok(res),
Err(e) => Err(db_error::IndexError(e)),
})
}
}

impl<'a> ClarityBackingStore for ReadOnlyMarfStore<'a> {
Expand Down
Loading

0 comments on commit 4fc1f28

Please sign in to comment.