syntax = "proto3"; package quilibrium.node.clock.pb; option go_package = "source.quilibrium.com/quilibrium/monorepo/node/protobufs"; import "channel.proto"; import "keys.proto"; // Represents a clock frame for a given filter. Clock frames are the primary // sequencing mechanism upon which the network derives consensus. As the master // pulse clock, this provides deterministic but random leader election. At the // data pulse clock level, this provides the same, within a quorum for data // sequencers. message ClockFrame { // The filter is used as a domain separator for input, but in the context of // verifiable delay functions, is simply prepended to the input field as input // for the VDF. bytes filter = 1; // A strictly monotonically-increasing frame number. Used for culling old // frames past a configurable cutoff point. uint64 frame_number = 2; // The self-reported timestamp from the proof publisher, encoded as an int64 // of the Unix epoch in milliseconds. Should be good until // 292278994-08-17 07:12:55.807, at which point, this is someone else's // problem. Timestamps are imperfect, but smoothed in a rolling window to // ensure a network and quorum-stable difficulty adjustment. Anomalies are // bounded such that a timestamp beyond ten times the average issuance rate // is discarded in preference to the runner up electees, unless there is // simply no alternative available (for example, if a network outage occurred // from an upgrade or bug). int64 timestamp = 3; // The difficulty level used for the frame. Difficulty is calculated based on // the previous 60 timestamps correlated with difficulties, such that the // interval smooths out to align to the type-defined rate. This is expected to // increase subtly with clock speed and future hardware implementations, but // due to incentive alignment associated with data proofs, not fastest clock // in the west, should be gradual. uint32 difficulty = 4; // The selector value of the previous frame's output, produced as a Poseidon // hash of the output. bytes parent_selector = 5; // The input data used for the VDF proof. For the master pulse clock, this is // the concatenation of the filter, frame number, difficulty, previous frame's // output, and the rolled state proof commitment input. For the data pulse // clocks, this is the concatenation of the filter, frame number, timestamp, // difficulty, issuer address, previous frame's output, along with data // mutation and availability proofs. Elements that are also in the fields of // the clock frame are not included in this field due to redundancy. For the // ceremony phase, this is a singular clock fusing master and data pulses. bytes input = 6; // The output data from the VDF, serialized as bytes. For Wesolowski, this is // an encoding of the 258 byte Y value concatenated with the 258 byte proof // value. bytes output = 7; // Any aggregate proofs to be rolled into the committed clock frame. repeated quilibrium.node.channel.pb.InclusionAggregateProof aggregate_proofs = 8; // The signature of the proof issuer. oneof public_key_signature { quilibrium.node.keys.pb.Ed448Signature public_key_signature_ed448 = 9; } } message ClockFrameParentSelectors { uint64 frame_number = 1; bytes parent_selector = 2; } // Represents a request for a range of clock frames. Used to stay synchronized // to the latest state. message ClockFramesRequest { // The filter is used as a domain separator for input to the frames. bytes filter = 1; // The earliest frame in the range requested. uint64 from_frame_number = 2; // The latest frame in the range requested, if provided. Capped to a maximum // size of 128 frames. uint64 to_frame_number = 3; // The optional parent selector. If provided, will perform a check to confirm // continuity, otherwise, will rewind the sync head to the beginning. bytes parent_selector = 4; // The optional range selectors. If provided, will perform a check against // them to optimize the provided deltas. repeated ClockFrameParentSelectors range_parent_selectors = 5; } // Represents a response for a range of clock frames. Used to stay synchronized // to the latest state. message ClockFramesResponse { // The filter is used as a domain separator for input to the frames. bytes filter = 1; // The earliest frame in the range response. Paginated to a maximum size of // 128 frames per response. uint64 from_frame_number = 2; // The latest frame in the range response. uint64 to_frame_number = 3; // The set of clock frames within the provided range. repeated ClockFrame clock_frames = 4; }