How to provide "time of entry authoring" automatically?

Correct. So are you looking for a timestamp that can be incorporated directly into the entry’s content?

Yep! That’s the one

Okay, yeah, you’re right — in that case it doesn’t exist until an agent commits the entry into their source chain. I just reread my earlier response… Both examples are for the ‘trusted notary’ case. Example 1 forces the trusted notary to commit an entry right then and there, so he can get the timestamp from the header, whereas example 2 gets the notary to make a call out to a timestamping daemon on his own machine.

But if you’re asking about ‘implicit trust’, then all my incredibly clever suggestions are useless :rofl: :rofl: :rofl: :rofl: I think the simple answer is, yeah, the agent would have to pass the timestamp in from her UI along with the rest of the entry data. If her instance needs do any timestamping headlessly, it could use the signal-to-timestamping-daemon (or signal-to-UI) idea as per the second trusted notary example above.

What about this flow?

  • new request hits the zome API
  • entry is constructed and written
  • entry header is read to retrieve timestamp
  • timestamp is written to a separate entry and linked to the main entry. Timestamp is part of the link tag.
  • timestamp is injected into response data as creation_time or similar
  • response data is sent; request ends

It would necessitate an extra link read to provide creation_time when reading the record later, but I think one additional DHT operation is pretty minimal- you can skip reading the entry itself if the timestamp is written to the link tag.

It’s a good MVP, IMO. In other timestamping scenarios there are just capabilities governing who gets to write the timestamps. I’m pretty sure the retrieval logic could be generic for all cases (ie. read all linked timestamps and average them).

Nice. One thing in particular stands out: the interface to the data being timestamped is clean; it doesn’t introduce any dependencies into the timestamping zome. That is, the only thing the timestamping zome understands is a request to timestamp some data (probably the hash of the content, for simplicity’s sake).

I presume that the response from the zome includes the creation_time as well as the proof of timestamping (either a generated signature or the hash of the timestamp entry), which can then be incorporated into the caller’s data?

I guess it could return that stuff if external callers are interested in knowing about it; but I can also see how timestamping nodes on the DHT might want to be “more anonymous” than to have their public keys broadcast to anyone asking.

So… I suppose I’m more or less happy with this approach. It feels like a bit of a screwaround but I can see how it’s actually the most appropriate way of managing it when I think through how data flows through Holochain core (local chain first; then DHT broadcast…)

Oh, this changes my understanding of what you’re working on — I’d assumed that you’d want the timestamping nodes to be well-known public nodes that everyone can trust. Can you tell me more about anonymous timestamping nodes?

Oh no, all of the above. Per the types outlined in my original post:

  • Trusted notary = timestamping nodes are well-known public nodes
  • Quorum time = timestamping nodes are random agents who are holding the content on the DHT
  • Trusted time (the topic of this thread) = there are no timestamping nodes, just the timestamp of when the entry was first written to its author’s local source chain

I think we’re on the same page with how this should work. My only query is why you think there needs to be some “signature” of the timestamping present. What you mean is that we just need to store a regular entry, right? 'Cos the entry will have a signature as part of its provenance data?

I’ve just realised that the above approach won’t work, because what I actually need is for the entry time to be part of the entry so that it automatically disambiguates new entries as they are created. Otherwise, creating a new entry with the same content as a previous one results in the same record being written and returned - this is not always what you want.

So this means we’re back to the only option being passing the timestamp in from the external client app - there is as yet no way to provide this information automatically.

I’m curious how people feel about adding the concept of a “request time” to Holochain API calls, that is automatically injected into the request as it enters the zome API membrane for the first time. Is such a differentiation even possible given the core architecture?

1 Like

So you’re problem is you want to put asynchronous events in a time series. Using approaches like this, you can really only guarantee that an event happened after a point in time. I believe this is more of a use case for a blockchain than a DHT. But that kind of goes back to something I’ve mentioned before, I think there needs to be a blockchain zome. If you want to take events, and put them in a “block” of time, that’s going to be a straightforward way to do it in a decentralized system.

The issue with a centralized authority is that you kind of remove the benefits of a decentralized system. What you have is a distributed database with a centralized API. If I can only post once a signature authority approves my post, there’s not much benefit to using a decentralized framework.

I think IOTA came up with an interesting solution that could work in Holochain. If you say that the confidence of an events occurrence in time increases with the amount of entries downstream from it, it helps to create a chronology. It wouldn’t be precise but it would help to establish that events happened after other events. Once again, this is moving in the direction of a “entry chain”. So I make a post, other people make posts and reference my header hash. Other people reference those posts. I now have a growing dag of entries that can establish a chronology. If users post entries to this DAG, they will help to establish a chronology that will be reasonably secure.

I would recommend reading about Lamport Clocks: https://en.wikipedia.org/wiki/Lamport_timestamps to see how this problem was handled historically. Also, verifiable delay functions https://eprint.iacr.org/2018/601.pdf are a modern approach that have some really interesting applications to these sorts of problems. Solana uses a combination of these techniques to build a chronology, and I would love to see a translation of these concepts to a DHT.

@rlkel0 that’s a great comment and set of links to go towards building robust timestamping solutions, like I’m exploring here:

For the purposes of this thread though, I’m just looking for the simplest option to get some kind of timestamp for records. Putting things in time series etc is well outside the scope, I’m just curious to know whether this can be left as a back-end implementation detail or has to be coded into the application layer of every app.

Currently the answer seems to be that if you want to record an authoring timestamp within the content of an entry, the UI needs to provide this. There is no metadata generated automatically by Holochain until after the entry is committed to the DHT.

If that be the case it would be nice to have such metadata. To provide for this, the initial request made to a Holochain DHT needs to be differentiated from all subsequent requests that are just syncing the initial entry. I’m not sure if this is possible; it depends on the internals of Holochain’s syncing logic. Can any core devs elaborate?

You could potentially use the header timestamps, although I think you’d need to ensure they’re monotonically increasing. I’m not sure if there’s anything that prevents a malicious agent from providing unreasonable timestamps. Agreeing on time in a distributed system is a whole other problem in itself though.

here’s where it is in the codebase:

I don’t think so. Not something I’m concerned about for this more permissive implementation, anyway.

The issue remains that ChainHeader::new is called during the write phase (internally in commit_entry or update_entry)- you can’t generate a ChainHeader in the pre-write phase of a transaction like you can with entry_address, in order to provide for API_CALL_TIME_SOURCE in something like:

hdk::commit_entry(
    &Entry::App("post".into(), Post{
        content,
        date_created: Iso8601::from(API_CALL_TIME_SOURCE),
    }.into())
);

You could just add a string field then.

You could just add a string field then.

Yes. But it’s not only adding the field to the Entry type definition and assigning it, is it? It’s also:

  • Adding a parameter to the inbound API request payload
  • Adding a parameter to the client-side GraphQL schema or zome API request adapter
  • Passing a new Date() in every client-side request

I don’t want to have to deal with all that plumbing… in any client/server system I would not have to do any of those things because I would have access to the system clock, or at least to the time the request was initiated. Why not allow for Holochain apps to do the same? In my view, the client shouldn’t have to be responsible for this logic- the conductor node should figure it out and report back. A request time determined by the zome API function handler is no more or less trustworthy than a request time passed in from the client app.

The issue remains that ChainHeader::new is called during the write phase (internally in commit_entry or update_entry)- you can’t generate a ChainHeader in the pre-write phase of a transaction like you can with entry_address, in order to provide for API_CALL_TIME_SOURCE in something like:

but then you also say:

I don’t want to have to deal with all that plumbing…

You’re asking for custom logic but you don’t want to write it? Literally every thing you add to your app is another thing you need to implement, so I’m not sure what the issue is? If you’re concerned about your ability to code this, there’s an example of this here: https://developer.holochain.org/docs/tutorials/coreconcepts/simple_micro_blog/ so you could pretty much copy it verbatim.

This makes me wonder, is your plan to have a website that runs on Holochain but not require users to operate nodes? There’s been some discussion about this, where user would be able to salt their private key using the data on nodes but keeping their password secret. So they would be able to sign and authenticate their requests on the frontend without running a node, it’s just a slightly different architecture. Then you would be able to make node operators function as notaries. You can have multiple nodes sign a transaction, perhaps you encourage node operators to co-sign time stamps to increase security?

@rlkel0 I think that what @pospi is looking for is a way for a node to add a simple timestamp to their entry content, no guarantees about whether it’s accurate or monotonic or anything. I can understand the desire to do this in the zome function itself; there are times (e.g., node-to-node messaging) when you don’t have access to the client/GUI’s time functions.

It seems reasonable to me — after all, the conductor already timestamps things — and it’s not the first time someone has asked for it. I’m already tracking it in this Trello card, and @freesig and I are going to start making feature requests as PRs rather than tickets. I think there are some other things higher up in the queue right now, but hang tight and we’ll see where it goes!

So how would that function compared to the header timestamp? Couldn’t the functionality of the header just be extended rather than creating two different ways to indicate the time of write?

Indeed — in some cases this is enough, but in most cases it isn’t, because you want some way of disambiguating entries that would otherwise have the same hash. On the DHT two entries containing the text “hello” will collapse into one entry with two author signatures. This isn’t what you want in, say, a messaging app, because if one agent deletes their “hello” they’ll delete it for everyone, even people who try to say “hello” in the future.

So what you want is some way of distinguishing those two identical messages, such that one agent can modify it without affecting anyone else’s message. Ideally this information should be semantically meaningful, not just a random number. Fortunately, adding an author ID and timestamp do add semantic value to that entry and distinguish it from all other entries with the same message. It may seem silly because you already have headers that contain that info, but I think the data should be able to stand on its own without needing to call up the header.

But you’ve got a chicken-and-egg problem if you want to take the entry’s source chain timestamp and insert it into the entry content because it doesn’t have a source chain timestamp until it’s committed. That’s where a timestamp function could come in handy.

@pospi you’re right; you wouldn’t need signatures for ‘trusted timestamp’ — I was suggesting a signature when I was still interpreting ‘trusted’ as ‘provably trusted’ rather than ‘implicitly trusted’.

Thankyou for that last post @pauldaoust - that is a succinct and exact description of the problem. I’m pleased to hear that others have been asking for this since it seems like necessary core functionality and a straightforward request.