-
Notifications
You must be signed in to change notification settings - Fork 0
/
ledger.go
320 lines (266 loc) · 12.1 KB
/
ledger.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
/*
* Copyright 2019 Insolar Technologies
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package core
import (
"context"
)
// DynamicRole is number representing a node role.
type DynamicRole int
const (
// DynamicRoleUndefined is used for special cases.
DynamicRoleUndefined = DynamicRole(iota)
// DynamicRoleVirtualExecutor is responsible for current pulse CPU operations.
DynamicRoleVirtualExecutor
// DynamicRoleVirtualValidator is responsible for previous pulse CPU operations.
DynamicRoleVirtualValidator
// DynamicRoleLightExecutor is responsible for current pulse Disk operations.
DynamicRoleLightExecutor
// DynamicRoleLightValidator is responsible for previous pulse Disk operations.
DynamicRoleLightValidator
// DynamicRoleHeavyExecutor is responsible for permanent Disk operations.
DynamicRoleHeavyExecutor
)
// IsVirtualRole checks if node role is virtual (validator or executor).
func (r DynamicRole) IsVirtualRole() bool {
switch r {
case DynamicRoleVirtualExecutor:
return true
case DynamicRoleVirtualValidator:
return true
}
return false
}
// Deprecated: remove after deleting TmpLedger
// Ledger is the global ledger handler. Other system parts communicate with ledger through it.
// FIXME: THIS INTERFACE IS DEPRECATED. USE DI.
type Ledger interface {
// Deprecated: remove after deleting TmpLedger
// GetArtifactManager returns artifact manager to work with.
GetArtifactManager() ArtifactManager
// Deprecated: remove after deleting TmpLedger
// GetJetCoordinator returns jet coordinator to work with.
GetJetCoordinator() JetCoordinator
// Deprecated: remove after deleting TmpLedger
// GetPulseManager returns pulse manager to work with.
GetPulseManager() PulseManager
// Deprecated: remove after deleting TmpLedger
// GetLocalStorage returns local storage to work with.
GetLocalStorage() LocalStorage
}
// PulseManager provides Ledger's methods related to Pulse.
//go:generate minimock -i github.com/insolar/insolar/core.PulseManager -o ../testutils -s _mock.go
type PulseManager interface {
// Set set's new pulse and closes current jet drop. If dry is true, nothing will be saved to storage.
Set(ctx context.Context, pulse Pulse, persist bool) error
}
// JetCoordinator provides methods for calculating Jet affinity
// (e.g. to which Jet a message should be sent).
//go:generate minimock -i github.com/insolar/insolar/core.JetCoordinator -o ../testutils -s _mock.go
type JetCoordinator interface {
// Me returns current node.
Me() RecordRef
// IsAuthorized checks for role on concrete pulse for the address.
IsAuthorized(ctx context.Context, role DynamicRole, obj RecordID, pulse PulseNumber, node RecordRef) (bool, error)
// QueryRole returns node refs responsible for role bound operations for given object and pulse.
QueryRole(ctx context.Context, role DynamicRole, obj RecordID, pulse PulseNumber) ([]RecordRef, error)
VirtualExecutorForObject(ctx context.Context, objID RecordID, pulse PulseNumber) (*RecordRef, error)
VirtualValidatorsForObject(ctx context.Context, objID RecordID, pulse PulseNumber) ([]RecordRef, error)
LightExecutorForObject(ctx context.Context, objID RecordID, pulse PulseNumber) (*RecordRef, error)
LightValidatorsForObject(ctx context.Context, objID RecordID, pulse PulseNumber) ([]RecordRef, error)
// LightExecutorForJet calculates light material executor for provided jet.
LightExecutorForJet(ctx context.Context, jetID RecordID, pulse PulseNumber) (*RecordRef, error)
LightValidatorsForJet(ctx context.Context, jetID RecordID, pulse PulseNumber) ([]RecordRef, error)
Heavy(ctx context.Context, pulse PulseNumber) (*RecordRef, error)
}
// ArtifactManager is a high level storage interface.
//go:generate minimock -i github.com/insolar/insolar/core.ArtifactManager -o ../testutils -s _mock.go
type ArtifactManager interface {
// GenesisRef returns the root record reference.
//
// Root record is the parent for all top-level records.
GenesisRef() *RecordRef
// RegisterRequest creates request record in storage.
RegisterRequest(ctx context.Context, object RecordRef, parcel Parcel) (*RecordID, error)
// RegisterValidation marks provided object state as approved or disapproved.
//
// When fetching object, validity can be specified.
RegisterValidation(ctx context.Context, object RecordRef, state RecordID, isValid bool, validationMessages []Message) error
// RegisterResult saves VM method call result.
RegisterResult(ctx context.Context, object, request RecordRef, payload []byte) (*RecordID, error)
// GetCode returns code from code record by provided reference according to provided machine preference.
//
// This method is used by VM to fetch code for execution.
GetCode(ctx context.Context, ref RecordRef) (CodeDescriptor, error)
// GetObject returns descriptor for provided state.
//
// If provided state is nil, the latest state will be returned (with deactivation check). Returned descriptor will
// provide methods for fetching all related data.
GetObject(ctx context.Context, head RecordRef, state *RecordID, approved bool) (ObjectDescriptor, error)
// HasPendingRequests returns true if object has unclosed requests.
HasPendingRequests(ctx context.Context, object RecordRef) (bool, error)
// GetDelegate returns provided object's delegate reference for provided type.
//
// Object delegate should be previously created for this object. If object delegate does not exist, an error will
// be returned.
GetDelegate(ctx context.Context, head, asType RecordRef) (*RecordRef, error)
// GetChildren returns children iterator.
//
// During iteration children refs will be fetched from remote source (parent object).
GetChildren(ctx context.Context, parent RecordRef, pulse *PulseNumber) (RefIterator, error)
// DeclareType creates new type record in storage.
//
// Type is a contract interface. It contains one method signature.
DeclareType(ctx context.Context, domain, request RecordRef, typeDec []byte) (*RecordID, error)
// DeployCode creates new code record in storage.
//
// Code records are used to activate prototype.
DeployCode(ctx context.Context, domain, request RecordRef, code []byte, machineType MachineType) (*RecordID, error)
// ActivatePrototype creates activate object record in storage. Provided prototype reference will be used as objects prototype
// memory as memory of created object. If memory is not provided, the prototype default memory will be used.
//
// Request reference will be this object's identifier and referred as "object head".
ActivatePrototype(
ctx context.Context,
domain, request, parent, code RecordRef,
memory []byte,
) (ObjectDescriptor, error)
// ActivateObject creates activate object record in storage. If memory is not provided, the prototype default
// memory will be used.
//
// Request reference will be this object's identifier and referred as "object head".
ActivateObject(
ctx context.Context,
domain, request, parent, prototype RecordRef,
asDelegate bool,
memory []byte,
) (ObjectDescriptor, error)
// UpdatePrototype creates amend object record in storage. Provided reference should be a reference to the head of
// the prototype. Provided memory well be the new object memory.
//
// Returned reference will be the latest object state (exact) reference.
UpdatePrototype(
ctx context.Context,
domain, request RecordRef,
obj ObjectDescriptor,
memory []byte,
code *RecordRef,
) (ObjectDescriptor, error)
// UpdateObject creates amend object record in storage. Provided reference should be a reference to the head of the
// object. Provided memory well be the new object memory.
//
// Returned reference will be the latest object state (exact) reference.
UpdateObject(
ctx context.Context,
domain, request RecordRef,
obj ObjectDescriptor,
memory []byte,
) (ObjectDescriptor, error)
// DeactivateObject creates deactivate object record in storage. Provided reference should be a reference to the head
// of the object. If object is already deactivated, an error should be returned.
//
// Deactivated object cannot be changed.
DeactivateObject(ctx context.Context, domain, request RecordRef, obj ObjectDescriptor) (*RecordID, error)
// State returns hash state for artifact manager.
State() ([]byte, error)
}
// CodeDescriptor represents meta info required to fetch all code data.
type CodeDescriptor interface {
// Ref returns reference to represented code record.
Ref() *RecordRef
// MachineType returns code machine type for represented code.
MachineType() MachineType
// Code returns code data.
Code() ([]byte, error)
}
// ObjectDescriptor represents meta info required to fetch all object data.
//go:generate minimock -i github.com/insolar/insolar/core.ObjectDescriptor -o ../testutils -s _mock.go
type ObjectDescriptor interface {
// HeadRef returns head reference to represented object record.
HeadRef() *RecordRef
// StateID returns reference to object state record.
StateID() *RecordID
// Memory fetches object memory from storage.
Memory() []byte
// IsPrototype determines if the object is a prototype.
IsPrototype() bool
// Code returns code reference.
Code() (*RecordRef, error)
// Prototype returns prototype reference.
Prototype() (*RecordRef, error)
// Children returns object's children references.
Children(pulse *PulseNumber) (RefIterator, error)
// ChildPointer returns the latest child for this object.
ChildPointer() *RecordID
// Parent returns object's parent.
Parent() *RecordRef
}
// RefIterator is used for iteration over affined children(parts) of container.
type RefIterator interface {
Next() (*RecordRef, error)
HasNext() bool
}
// LocalStorage allows a node to save local data.
//go:generate minimock -i github.com/insolar/insolar/core.LocalStorage -o ../testutils -s _mock.go
type LocalStorage interface {
// Set saves data in storage.
Set(ctx context.Context, pulse PulseNumber, key []byte, data []byte) error
// Get retrieves data from storage.
Get(ctx context.Context, pulse PulseNumber, key []byte) ([]byte, error)
// Iterate iterates over all record with specified prefix and calls handler with key and value of that record.
//
// The key will be returned without prefix (e.g. the remaining slice) and value will be returned as it was saved.
Iterate(ctx context.Context, pulse PulseNumber, prefix []byte, handler func(k, v []byte) error) error
}
// KV is a generic key/value struct.
type KV struct {
K []byte
V []byte
}
// KVSize returns size of key/value array in bytes.
func KVSize(kvs []KV) (amount int64) {
for _, kv := range kvs {
amount += int64(len(kv.K) + len(kv.V))
}
return
}
// StorageExportResult represents storage data view.
type StorageExportResult struct {
Data map[string]interface{}
NextFrom *PulseNumber
Size int
}
// StorageExporter provides methods for fetching data view from storage.
type StorageExporter interface {
// Export returns data view from storage.
Export(ctx context.Context, fromPulse PulseNumber, size int) (*StorageExportResult, error)
}
var (
// TODOJetID temporary stub for passing jet ID in ledger functions
// on period Jet ID full implementation
// TODO: remove it after jets support readyness - @nordicdyno 5.Dec.2018
TODOJetID = *NewRecordID(PulseNumberJet, nil)
DomainID = *NewRecordID(0, nil)
)
// PulseStorage provides the interface for fetching current pulse of the system
//go:generate minimock -i github.com/insolar/insolar/core.PulseStorage -o ../testutils -s _mock.go
type PulseStorage interface {
Current(ctx context.Context) (*Pulse, error)
}
//go:generate minimock -i github.com/insolar/insolar/core.ArtifactManagerMessageHandler -o ../testutils -s _mock.go
type ArtifactManagerMessageHandler interface {
ResetEarlyRequestCircuitBreaker(context.Context)
CloseEarlyRequestCircuitBreakerForJet(context.Context, RecordID)
}