-
Notifications
You must be signed in to change notification settings - Fork 989
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add state archival getledgerentry endpoint #4623
base: master
Are you sure you want to change the base?
Conversation
0865066
to
4cd8801
Compare
ac9f21a
to
45ab670
Compare
45ab670
to
e45fdf4
Compare
This branch crashes intermittently. Config and captured logs below. Config
Logs
|
Pretty exciting 👏🏻 . I am interested in the interface. Comments about the request body and response from above: Request Body:
Response:
1️⃣ – order 2️⃣ – 3️⃣ – 4️⃣ – The 5️⃣ – If implemented the above comments would result in: Request Body:
Response:
|
Thinking about this further, this API is quite similar to the JSON-RPC API that RPC is exposing. I think we should consider, either in this release or next, changing the shape of this API, and changing the shape of the RPC JSON-RPC API to align (which we can do in a backwards compatible way), so that core's Query endpoints are actually the same API as – and a subset and superset of – the RPC JSON-RPC API. Why: The APIs are almost the same already and communicate the same data. In the Ethereum ecosystem the RPC API is a standardised thing that multiple implementations and services implement. It allows tooling to move between using different tools and services seamlessly and is generally a very cool experience as a developer. Not the full RPC API needs implementing. Core is after-all the lowest level RPC. cc @tomerweller This is something we discussed recently. |
Totally agree with @leighmcculloch. The prior art in the ethereum ecosystem demonstrates that having a uniform API across the stack (but with different implementations and retention policy) makes it easy for new services to emerge and for developers to choose the right layer of the stack for them. This specifically can also make stellar-core more independently useful |
Thanks for the feedback. I don't design many HTTP web APIs, so I have no objections for these changes. RPC has integrated the current interface, so I'll leave it as is for now so I can get the early integration test working. @Shaptic any thoughts on these API changes? |
@SirTyson ☝🏻 |
Just fyi, we don't assume ordering in RPC (the existing SQL-based impl. also has no order guarantees), so we need the key returned on
The implication is that this key represents a pending new ledger key in the state. I guess
It's mildly annoying to re-coordinate the API work that's already been done for an API that only RPC uses (I disagree with the implication that people should Core directly), but otherwise they seem fine. (As long as there's no implication to make the response match the actual JSON-RPC spec, which I don't think there is, but I'm just double-checking.) |
Just to expand on my disagreement with this:
If the end-goal is to resolve those issues, that's awesome and it can eventually be a first-class "RPC", but there's a long way to go so I certainly don't think it's at a point where we should encourage people to use it directly today. (This isn't a knock against Core btw: it was intentionally designed this way and that's been perfectly fine so far 💪) |
No, currently there is no defined ordering. |
In p23, |
Description
Resolves the p23 portions of #4397 by adding the
getledgerentry
HTTP endpoint, which returns LedgerEntries with the relevant TTL and state information.This is also the cutoff point for early RPC integration of p23. Compared to the last core release (22.1), RPC will need to integrate the following changes. Note that all these changes are protocol gated and are only in effect if the package is running protocol 23.
RPC Integration Changes
Persistent entry eviction
Persistent
CONTRACT_DATA
entries and allCONTRACT_CODE
entries are now subject to eviction. This means that an expired entry can be evicted and deleted from the live BucketList during eviction scans.evictedTemporaryLedgerKeys
will now contains evicted temporaryCONTRACT_DATA
keys and TTLs as before, but will now additionally holdCONTRACT_CODE
and persistentCONTRACT_DATA
keys along with their TTLs.evictedPersistentLedgerEntries
is still never populated. With the final p23 build we will renameevictedTemporaryLedgerKeys
but it's not included in this build. XDR changes will come later.Changes to Restoration Meta
Restoration meta will depend on the "state" of the entry being restored. The two states of the entry being restored are
archived
: Entry has an expired TTL, but still lives on the live BucketList. Entry has not yet been evicted, so the key has not been populated in theevictedTemporaryLedgerKeys
vector yet.evicted
: Entry has been fully evicted from the live BucketList and is now stored in the Hot Archive BucketList. Key has been emitted in theevictedTemporaryLedgerKeys
vector.Not: I realize this terminology is a bit confusing because we now have two "archived" states. That being said, the
evicted
state is only relevant to RPC and core and is completely abstracted from developers and people invoking contracts. Given the feedback from the original expiration terminology, I'd like to avoid it if at all possible and use the archived vs evicted terminology.RestoreFootprintOp
will produce meta as follows.archived
keysIn protocols < 23, meta was as follows:
In protocol >= 23, meta is as follows:
evicted
keysIn protocol < 23, there were no evicted key restorations.
In protocol >= 23, meta is as follows:
getledgerentry
captive-core endpoint for Ledger StateWith protocol 23, ledger DBs are getting more complicated, as entries are stored both in the live BucketList DB and in the Hot Archive DB. To properly simulate TXs, it will be necessary to know what DB an entry is in, as well as it's "state" wrt TTL value. This logic is complicated to replicate outside of core, especially since much of the state information is intrinsic to the structure of the BucketList and may be expensive to replicate in SQL. Instead of maintaining a DB of ledger state, it is recommended that RPC use the new
getledgerentry
captive-core endpoint for all LedgerState access. Core now comes with a multithreaded HTTP server implementation that seems sufficiently fast over local host for all state accesses see this.By default, this "query server" is disabled in core. It can be enabled and configured with the following captive-core flags
Once enabled, the following endpoint will be available:
getledgerentry
Used to query both live and archived LedgerEntries. While
getledgerentryraw
does simple key-value lookupon the live ledger,
getledgerentry
will query a given key in both the live BucketList and Hot Archive BucketList.It will also report whether an entry is archived, evicted, or live, and return the entry's current TTL value.
A POST request with the following body:
ledgerSeq=NUM&key=Base64&key=Base64...
ledgerSeq
: An optional parameter, specifying the ledger snapshot to base the query on.If the specified ledger in not available, a 404 error will be returned. If this parameter
is not set, the current ledger is used.
key
: A series of Base64 encoded XDR strings specifying theLedgerKey
to query. TTL keysmust not be queried and will return 400 if done so.
A JSON payload is returned as follows:
entries
: A list of entries for each queried LedgerKey. Everykey
queried is guaranteed tohave a corresponding entry returned.
e
: Either theLedgerEntry
orLedgerKey
for a given key encoded as a Base64 string. If a keyis live or archived,
e
contains the correspondingLedgerEntry
. If a key does not exist(including expired temporary entries)
e
contains the correspondingLedgerKey
.state
: One of the following values:live
: Entry is live.new
: Entry does not exist. Either the entry has never existed or is an expired temp entry.archived
: Entry is archived, counts towards disk resources.ttl
: An optional value, only returned for live Soroban entries. Containsa uint32 value for the entry's
liveUntilLedgerSeq
.ledgerSeq
: The ledger number on which the query was performed.Classic entries will always return a state of
live
ornew
.If a classic entry does not exist, it will have a state of
new
.Similarly, temporary Soroban entries will always return a state of
live
ornew
. If a temporary entry does not exist or has expired, itwill have a state of
new
.This endpoint will always give correct information for archived entries. Even
if an entry has been archived and evicted to the Hot Archive, this endpoint will
still the archived entry's full
LedgerEntry
as well as the proper state.RPC Testing
To test the new changes, RPC will want to have tests that restore entries that are in both the
archived
andevicted
state. What I've been doing in my tests is populating state with a bunch of persistent entries, letting them expire, but setting my eviction scan parameters such that only 1 or 2 entries are evicted at a time. You can keep track of an entry's starting TTL and whether or not you have seen eviction meta to determine it's state within the test. These flags are helpful.Make sure you also have the QUERY_SERVER flags set as well so you can use the core endpoint. I think this has been thorough enough, but if I missed anything CAP 62 and CAP 66 have full specs.
Checklist
clang-format
v8.0.0 (viamake format
or the Visual Studio extension)