Annouce Ledger Candid: your missing candid interface to the NNS ledger

It has long been a mystery on why NNS ledger is missing some important interface in candid that it already offers in protobuf. But wait no more! I’ve build a proxy canister ockk2-xaaaa-aaaai-aaaua-cai that offers two extra interfaces:

service : {
  block : (nat64) -> (variant { Ok: variant { Ok: Block; Err: CanisterId }; Err: text });
  tip_of_chain : () -> (variant { Ok: TipOfChain; Err: text });
}

PRs are welcome! Please help yourself if you’d like more interfaces!

Know Caveat: the query interfaces have to turn into update calls because we cannot make secure query calls from an app subnet to the NNS subnet.

9 Likes

Canlista listing: Ledger Candid

BTW, I do plan to make this canister immutable soon (just like The Randomness Oracle), so that other people/canisters can safely depend on it.

6 Likes

This is super useful, thank you!!

1 Like

If you get back to messing with this, having get_blocks_pb that returns a set of blocks from n to n+size would be great(especially since there is only one trx per block). If you have to look at every block you end up having to waste a bunch of cycles pulling blocks one at a time. You’ll probably want to cap it at a certain number of blocks so you don’t hit the 2MB limit.

Yes, we’re currently working on changing the interface along these lines

@quinto About how much is accessible through this? I tried looking up a transaction from a couple of days ago and got an error. Going back about 1000 blocks seemed to work ok. I was just curious what the limit is before things go to the archive canister.

Good question!

The candid interface just forwards the call to the ledger canister’s protobuf interface. So maybe this is for the DFINITY team to answer. @bogwar can you help?

The ledger keeps a cache of between 1000 and 2000 transactions: whenever it gets to 2000 it archives the 1000 oldest transactions.

I’ll expand a bit on the Bogdan’s answer:

The main ledger canister only stores 1-2K of blocks and everything else is sent to “ledger archive” canisters.
The client is supposed to

  1. Fetch the assignment of blocks to canisters.
  2. Route block fetch requests appropriately.

The issue is that the assignment of the most recent blocks might change while the step (2) is being executed. This interface is error prone and hard to use.

One part of the initiative to allow canisters transfer ICPs is to provide a stable, properly designed Candid interface for ledger. The first version of the interface will only contain transfer and account_balance methods, but we’re planning to extend it to expose all capabilities of ledger.

We’ll later add a block syncing interface that doesn’t use the error-prone communication pattern mentioned above. It will be a single method (something like fetch_blocks_since : (Height, Limit) -> (FetchBlocksResponse) query).
The result will contain

  1. The tip of the chain (with optional certification).
  2. Blocks in the specified range stored by the Ledger.
  3. If some blocks are archived, the result will contain a mapping from block ranges to functions that fetch them.

Unfortunately, I don’t have an ETA for the block fetching interface now.

5 Likes

I may be missing something, but doesn’t this mean that canisters holding ICP is effectively nerfed because the canisters won’t be able to get information about who sent them the ICP? Or will we have access to the notify pathway?

1 Like

That is a very good point.
We’ll prioritize shipping the proper block fetching interface with the first version then.

3 Likes

Hi, thanks bro! this is quite helpful! So if I would like to try it at local, how I would do that? In case I deployed a ledger canister replica on local network, and I should deployed ur canister on my local network Also, so how I could do to deploy it so the proxy can work properly?

1 Like

Does the Ledger Candid interface handle archived blocks? Is there a way to query the ledger archive for blocks?