Skip to content

Commit ec16cc9

Browse files
committed
remote ledger service
1 parent d790588 commit ec16cc9

10 files changed

Lines changed: 1896 additions & 101 deletions

ledger/ledger.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,54 @@ type Ledger interface {
4848
StateByIndex(index int) (State, error)
4949
}
5050

51+
// PayloadlessLedger is the payloadless-mode counterpart of [Ledger]. It is a
52+
// stateful fork-aware key/value storage that stores only leaf hashes
53+
// (HashLeaf(path, value)) per register rather than the original payload values.
54+
// Reads therefore return leaf hashes, not values, and the proof type is
55+
// [PayloadlessTrieBatchProof] rather than [Proof] (an encoded TrieBatchProof).
56+
//
57+
// In production, *complete.PayloadlessLedger satisfies this interface by
58+
// construction. The interface lives here (and not in ledger/complete) so
59+
// downstream consumers — committer, remote gRPC service, future verification
60+
// clients — can depend on the payloadless ledger without importing
61+
// ledger/complete and pulling in WAL/forest infrastructure.
62+
type PayloadlessLedger interface {
63+
// PayloadlessLedger implements methods needed to be ReadyDone aware
64+
module.ReadyDoneAware
65+
66+
// InitialState returns the initial state of the ledger
67+
InitialState() State
68+
69+
// HasState returns true if the given state exists inside the ledger
70+
HasState(state State) bool
71+
72+
// HasPaths reports, for each key in the query, whether the corresponding
73+
// path has an allocated register at the query's state. Used by callers
74+
// that need register-existence checks without retrieving leaf hashes.
75+
HasPaths(query *Query) ([]bool, error)
76+
77+
// GetSingleLeafHash returns the leaf hash for a single key at the
78+
// query's state. Returns nil if the path is unallocated or the leaf
79+
// represents an empty register.
80+
GetSingleLeafHash(query *QuerySingleValue) (*hash.Hash, error)
81+
82+
// GetLeafHashes returns leaf hashes for the given slice of keys at the
83+
// query's state. A nil entry indicates an unallocated path or an empty
84+
// leaf. The returned slice is aligned with the query's Keys order.
85+
GetLeafHashes(query *Query) ([]*hash.Hash, error)
86+
87+
// Set updates a list of keys with new values at the given state and
88+
// returns the new state and the resulting trie update. The trie update
89+
// records the writes regardless of payloadless storage; only the
90+
// payload bytes are discarded.
91+
Set(update *Update) (newState State, trieUpdate *TrieUpdate, err error)
92+
93+
// Prove returns a payloadless batch proof for the given keys at the
94+
// query's state. Encoded with [EncodePayloadlessTrieBatchProof] on the
95+
// wire; consumers must decode with [DecodePayloadlessTrieBatchProof].
96+
Prove(query *Query) (*PayloadlessTrieBatchProof, error)
97+
}
98+
5199
// Query holds all data needed for a ledger read or ledger proof
52100
type Query struct {
53101
state State

ledger/payloadless_ledger.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package ledger

ledger/protobuf/ledger.pb.go

Lines changed: 291 additions & 37 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ledger/protobuf/ledger.proto

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,81 @@ message ProofResponse {
116116
bytes proof = 1; // Encoded Proof (opaque to gRPC)
117117
}
118118

119+
// LedgerMode reports the operating mode of the ledger server.
120+
enum LedgerMode {
121+
LEDGER_MODE_UNSPECIFIED = 0;
122+
LEDGER_MODE_FULL = 1;
123+
LEDGER_MODE_PAYLOADLESS = 2;
124+
}
125+
126+
// ServerInfoResponse reports server metadata such as the operating mode.
127+
message ServerInfoResponse {
128+
LedgerMode mode = 1;
129+
}
130+
131+
// LedgerInfoService reports mode and other metadata about the ledger server.
132+
// It is registered unconditionally on every ledger gRPC server regardless of
133+
// whether the process is running in full or payloadless mode. Clients call
134+
// ServerInfo at startup to verify they are talking to a server in the
135+
// expected mode.
136+
service LedgerInfoService {
137+
// ServerInfo returns metadata about this ledger server, including its
138+
// operating mode.
139+
rpc ServerInfo(google.protobuf.Empty) returns (ServerInfoResponse);
140+
}
141+
142+
// LeafHash is a 32-byte HashLeaf(path, value).
143+
// An empty `hash` (length 0) indicates the path is unallocated.
144+
message LeafHash {
145+
bytes hash = 1;
146+
}
147+
148+
// LeafHashResponse contains a single leaf hash.
149+
message LeafHashResponse {
150+
LeafHash leaf_hash = 1;
151+
}
152+
153+
// LeafHashesResponse contains a slice of leaf hashes, one per input key,
154+
// in the same order as the request.
155+
message LeafHashesResponse {
156+
repeated LeafHash leaf_hashes = 1;
157+
}
158+
159+
// HasPathsResponse reports, for each input key, whether the key has an
160+
// allocated register at the requested state.
161+
message HasPathsResponse {
162+
repeated bool exists = 1;
163+
}
164+
165+
// PayloadlessLedgerService provides remote access to a payloadless ledger.
166+
// Unlike LedgerService, reads return leaf hashes (HashLeaf(path, value))
167+
// rather than payload values. A server registers either LedgerService or
168+
// PayloadlessLedgerService at startup, never both.
169+
service PayloadlessLedgerService {
170+
// InitialState returns the initial state of the ledger.
171+
rpc InitialState(google.protobuf.Empty) returns (StateResponse);
172+
173+
// HasState checks if the given state exists in the ledger.
174+
rpc HasState(StateRequest) returns (HasStateResponse);
175+
176+
// HasPaths reports, for each input key, whether the key has an allocated
177+
// register at the requested state.
178+
rpc HasPaths(GetRequest) returns (HasPathsResponse);
179+
180+
// GetSingleLeafHash returns the leaf hash for a single key at a specific
181+
// state. An empty hash indicates the path is unallocated.
182+
rpc GetSingleLeafHash(GetSingleValueRequest) returns (LeafHashResponse);
183+
184+
// GetLeafHashes returns leaf hashes for multiple keys at a specific state.
185+
rpc GetLeafHashes(GetRequest) returns (LeafHashesResponse);
186+
187+
// Set updates keys with new values at a specific state and returns the
188+
// new state. The server discards the keys after hashing; only the values
189+
// contribute to the trie.
190+
rpc Set(SetRequest) returns (SetResponse);
191+
192+
// Prove returns a payloadless batch proof for the given keys at a
193+
// specific state. Proofs carry leaf hashes rather than payload values.
194+
rpc Prove(ProveRequest) returns (ProofResponse);
195+
}
196+

0 commit comments

Comments
 (0)