We, the boundary node team, are excited to announce a step forward in transparency and insights for you guys, the Internet Computer community! With the completion of the Levitron milestone, we are making the API Boundary Node (API BN) access logs publicly available in real-time.
This means you can now get visibility into how the Internet Computer and its canisters are being used. These logs offer new insights into canister usage, daily active users, and temporal behavior.
The key highlights are:
Real-time and decentralized access: stream the access logs directly from the API BNs without any intermediary.
Privacy-preserving: logs include client IDs (salted hashes) but no sensitive user data like IP addresses or sender principals.
Future authenticity: upcoming SEV-SNP-enabled API BNs will allow clients to attest to the logs’ integrity.
Start streaming logs immediately and build your own storage for historical data.
We believe this will be a great resource for developers and anyone interested in understanding the Internet Computer’s activity. Let us know what insights you discover!
I’d like to just take a moment to appreciate that DFINITY still does this work. I doubt many people were clamoring for this, but it is so important for the long-term transparency of how the IC operates. Amazing work!
Quick question…if we analyze these logs and find a salt that is a little chatty, do we have the salting algo that we can use on the canister side to block it(or use it in motoko for our inspect functions?) I guess that might reveal the info. Perhaps there is room to pass it in at the system level somehow? I guess it also depends on how stable the clientIds are.(what is used to produce them?)
We really appreciate the kind words, they mean a lot to us!
About the salt and the client id:
The client id is computed by concatenating the sender principal and the client IP address, then hashing it with a secret salt (using SHA3-256), and finally taking the first 16 bytes of the result.
The salt comes from the “salt-sharing” canister, which only allows API BNs to fetch the salt and rotates it every month.
Even if you knew the salt, it would be extremely difficult for you to “revert” the client IDs back to the sender principal and client IP. You could try to build a rainbow table, but the “input space” is just way too huge (prinicipals can have up to 29 bytes and IP addresses up to 16 bytes for IPv6).
This doesn’t require an answer, but just in case someone happens to known:
I tried to vibe code a web app using Windsurf (as I’m currently testing Juno’s LLM documentation) and those WebSockets. As a starting point, I used the Rust example you provided and asked the AI to translate it for the frontend. However, it struggled with converting the fetch_api_boundary_nodes_by_subnet_id function from the Agent to JS code. Fair enough, I don’t know the answer either .
So just out of curiosity, I was wondering if that call exist in the frontend environment too? Is it somehow exposed by Agent-js?
Again, really no need to dig into it only if someone knows off the top of their head. It was more an experiment that an important task.
The by_subnet_id part is just needed to route the read_state to a replica and the by_canister_id equivalent exists as well: You can specify any subnet ID or any canister ID and you will get an answer
I tried feeding your answer to Windsurf. It started off well, understanding that it had to use Agent-js for the lookup and certificate, but it didn’t manage to implement it. Just an experiment, I spent a few minutes trying to guide it but ultimately gave up. Really good to know nonetheless!