forked from gagliardetto/solana-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
instruction_error.go
565 lines (450 loc) · 21.2 KB
/
instruction_error.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
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
package solana
import (
"fmt"
"sync"
)
var (
customErrorResolvers = map[PublicKey]func(int) (error, bool){}
customErrorResolverMU sync.RWMutex
)
func RegisterCustomInstructionErrorResolver(progID PublicKey, f func(int) (error, bool)) {
customErrorResolverMU.Lock()
defer customErrorResolverMU.Unlock()
customErrorResolvers[progID] = f
}
func ResolveCustomInstructionError(progID PublicKey, code int) (error, bool) {
customErrorResolverMU.RLock()
defer customErrorResolverMU.RUnlock()
resolver, ok := customErrorResolvers[progID]
if !ok {
return nil, false
}
return resolver(code)
}
type InstructionError interface {
error
xx_isInstructionError()
}
func ParseInstructionError(err interface{}, progID *PublicKey) (InstructionError, bool) {
switch t := err.(type) {
case string:
return parseInstructionErrorString(t)
case map[string]interface{}:
return parseInstructionErrorObject(t, progID)
default:
return nil, false
}
}
func parseInstructionErrorObject(err map[string]interface{}, progID *PublicKey) (InstructionError, bool) {
code, ok := asFloat64(err["Custom"])
if !ok {
return nil, false
}
var cause error
if progID != nil {
cause, _ = ResolveCustomInstructionError(*progID, int(code))
}
return &InstructionError_Custom{
Code: uint32(code),
Cause: cause,
}, true
}
func parseInstructionErrorString(err string) (InstructionError, bool) {
switch err {
case "GenericError":
return InstructionError_GenericError{}, true
case "InvalidArgument":
return InstructionError_InvalidArgument{}, true
case "InvalidInstructionData":
return InstructionError_InvalidInstructionData{}, true
case "InvalidAccountData":
return InstructionError_InvalidAccountData{}, true
case "AccountDataTooSmall":
return InstructionError_AccountDataTooSmall{}, true
case "InsufficientFunds":
return InstructionError_InsufficientFunds{}, true
case "IncorrectProgramId":
return InstructionError_IncorrectProgramId{}, true
case "MissingRequiredSignature":
return InstructionError_MissingRequiredSignature{}, true
case "AccountAlreadyInitialized":
return InstructionError_AccountAlreadyInitialized{}, true
case "UninitializedAccount":
return InstructionError_UninitializedAccount{}, true
case "UnbalancedInstruction":
return InstructionError_UnbalancedInstruction{}, true
case "ModifiedProgramId":
return InstructionError_ModifiedProgramId{}, true
case "ExternalAccountLamportSpend":
return InstructionError_ExternalAccountLamportSpend{}, true
case "ExternalAccountDataModified":
return InstructionError_ExternalAccountDataModified{}, true
case "ReadonlyLamportChange":
return InstructionError_ReadonlyLamportChange{}, true
case "ReadonlyDataModified":
return InstructionError_ReadonlyDataModified{}, true
case "DuplicateAccountIndex":
return InstructionError_DuplicateAccountIndex{}, true
case "ExecutableModified":
return InstructionError_ExecutableModified{}, true
case "RentEpochModified":
return InstructionError_RentEpochModified{}, true
case "NotEnoughAccountKeys":
return InstructionError_NotEnoughAccountKeys{}, true
case "AccountDataSizeChanged":
return InstructionError_AccountDataSizeChanged{}, true
case "AccountNotExecutable":
return InstructionError_AccountNotExecutable{}, true
case "AccountBorrowFailed":
return InstructionError_AccountBorrowFailed{}, true
case "AccountBorrowOutstanding":
return InstructionError_AccountBorrowOutstanding{}, true
case "DuplicateAccountOutOfSync":
return InstructionError_DuplicateAccountOutOfSync{}, true
case "InvalidError":
return InstructionError_InvalidError{}, true
case "ExecutableDataModified":
return InstructionError_ExecutableDataModified{}, true
case "ExecutableLamportChange":
return InstructionError_ExecutableLamportChange{}, true
case "ExecutableAccountNotRentExempt":
return InstructionError_ExecutableAccountNotRentExempt{}, true
case "UnsupportedProgramId":
return InstructionError_UnsupportedProgramId{}, true
case "CallDepth":
return InstructionError_CallDepth{}, true
case "MissingAccount":
return InstructionError_MissingAccount{}, true
case "ReentrancyNotAllowed":
return InstructionError_ReentrancyNotAllowed{}, true
case "MaxSeedLengthExceeded":
return InstructionError_MaxSeedLengthExceeded{}, true
case "InvalidSeeds":
return InstructionError_InvalidSeeds{}, true
case "InvalidRealloc":
return InstructionError_InvalidRealloc{}, true
case "ComputationalBudgetExceeded":
return InstructionError_ComputationalBudgetExceeded{}, true
case "PrivilegeEscalation":
return InstructionError_PrivilegeEscalation{}, true
case "ProgramEnvironmentSetupFailure":
return InstructionError_ProgramEnvironmentSetupFailure{}, true
case "ProgramFailedToComplete":
return InstructionError_ProgramFailedToComplete{}, true
case "ProgramFailedToCompile":
return InstructionError_ProgramFailedToCompile{}, true
case "Immutable":
return InstructionError_Immutable{}, true
case "IncorrectAuthority":
return InstructionError_IncorrectAuthority{}, true
case "AccountNotRentExempt":
return InstructionError_AccountNotRentExempt{}, true
case "InvalidAccountOwner":
return InstructionError_InvalidAccountOwner{}, true
case "ArithmeticOverflow":
return InstructionError_ArithmeticOverflow{}, true
case "UnsupportedSysvar":
return InstructionError_UnsupportedSysvar{}, true
case "IllegalOwner":
return InstructionError_IllegalOwner{}, true
default:
return InstructionError_Undefined(err), true
}
}
type InstructionError_Undefined string
func (v InstructionError_Undefined) Error() string {
return string(v)
}
func (InstructionError_Undefined) xx_isInstructionError() {}
// Defined [here](https://github.com/solana-labs/solana/blob/f6371cce176d481b4132e5061262ca015db0f8b1/sdk/program/src/instruction.rs#L23).
// The program instruction returned an error
type InstructionError_GenericError struct{}
func (InstructionError_GenericError) Error() string { return "generic instruction error" }
func (InstructionError_GenericError) xx_isInstructionError() {}
// The arguments provided to a program were invalid
type InstructionError_InvalidArgument struct{}
func (InstructionError_InvalidArgument) Error() string { return "invalid program argument" }
func (InstructionError_InvalidArgument) xx_isInstructionError() {}
// An instruction's data contents were invalid
type InstructionError_InvalidInstructionData struct{}
func (InstructionError_InvalidInstructionData) Error() string { return "invalid instruction data" }
func (InstructionError_InvalidInstructionData) xx_isInstructionError() {}
// An account's data contents was invalid
type InstructionError_InvalidAccountData struct{}
func (InstructionError_InvalidAccountData) Error() string {
return "invalid account data for instruction"
}
func (InstructionError_InvalidAccountData) xx_isInstructionError() {}
// An account's data was too small
type InstructionError_AccountDataTooSmall struct{}
func (InstructionError_AccountDataTooSmall) Error() string {
return "account data too small for instruction"
}
func (InstructionError_AccountDataTooSmall) xx_isInstructionError() {}
// An account's balance was too small to complete the instruction
type InstructionError_InsufficientFunds struct{}
func (InstructionError_InsufficientFunds) Error() string { return "insufficient funds for instruction" }
func (InstructionError_InsufficientFunds) xx_isInstructionError() {}
// The account did not have the expected program id
type InstructionError_IncorrectProgramId struct{}
func (InstructionError_IncorrectProgramId) Error() string {
return "incorrect program id for instruction"
}
func (InstructionError_IncorrectProgramId) xx_isInstructionError() {}
// A signature was required but not found
type InstructionError_MissingRequiredSignature struct{}
func (InstructionError_MissingRequiredSignature) Error() string {
return "missing required signature for instruction"
}
func (InstructionError_MissingRequiredSignature) xx_isInstructionError() {}
// An initialize instruction was sent to an account that has already been initialized.
type InstructionError_AccountAlreadyInitialized struct{}
func (InstructionError_AccountAlreadyInitialized) Error() string {
return "instruction requires an uninitialized account"
}
func (InstructionError_AccountAlreadyInitialized) xx_isInstructionError() {}
// An attempt to operate on an account that hasn't been initialized.
type InstructionError_UninitializedAccount struct{}
func (InstructionError_UninitializedAccount) Error() string {
return "instruction requires an initialized account"
}
func (InstructionError_UninitializedAccount) xx_isInstructionError() {}
// UnbalancedInstruction is an error that occurs when a program's instruction
// lamport balance does not equal the balance after the instruction.
type InstructionError_UnbalancedInstruction struct{}
func (InstructionError_UnbalancedInstruction) Error() string {
return "sum of account balances before and after instruction do not match"
}
func (InstructionError_UnbalancedInstruction) xx_isInstructionError() {}
// ModifiedProgramId is an error that occurs when a program modifies an
// account's program id.
type InstructionError_ModifiedProgramId struct{}
func (InstructionError_ModifiedProgramId) Error() string {
return "instruction modified the program id of an account"
}
func (InstructionError_ModifiedProgramId) xx_isInstructionError() {}
// ExternalAccountLamportSpend is an error that occurs when a program spends
// the lamports of an account that doesn't belong to it.
type InstructionError_ExternalAccountLamportSpend struct{}
func (InstructionError_ExternalAccountLamportSpend) Error() string {
return "instruction spent from the balance of an account it does not own"
}
func (InstructionError_ExternalAccountLamportSpend) xx_isInstructionError() {}
// ExternalAccountDataModified is an error that occurs when a program modifies
// the data of an account that doesn't belong to it.
type InstructionError_ExternalAccountDataModified struct{}
func (InstructionError_ExternalAccountDataModified) Error() string {
return "instruction modified data of an account it does not own"
}
func (InstructionError_ExternalAccountDataModified) xx_isInstructionError() {}
// ReadonlyLamportChange is an error that occurs when a read-only account's
// lamports are modified.
type InstructionError_ReadonlyLamportChange struct{}
func (InstructionError_ReadonlyLamportChange) Error() string {
return "instruction changed the balance of a read-only account"
}
func (InstructionError_ReadonlyLamportChange) xx_isInstructionError() {}
// ReadonlyDataModified is an error that occurs when a read-only account's data
// is modified.
type InstructionError_ReadonlyDataModified struct{}
func (InstructionError_ReadonlyDataModified) Error() string {
return "instruction modified data of a read-only account"
}
func (InstructionError_ReadonlyDataModified) xx_isInstructionError() {}
// DuplicateAccountIndex is an error that occurs when an account is referenced
// more than once in a single instruction.
type InstructionError_DuplicateAccountIndex struct{}
func (InstructionError_DuplicateAccountIndex) Error() string {
return "instruction contains duplicate accounts"
}
func (InstructionError_DuplicateAccountIndex) xx_isInstructionError() {}
// ExecutableModified is an error that occurs when an instruction changes the
// executable bit of an account.
type InstructionError_ExecutableModified struct{}
func (InstructionError_ExecutableModified) Error() string {
return "instruction changed executable bit of an account"
}
func (InstructionError_ExecutableModified) xx_isInstructionError() {}
// RentEpochModified is an error that occurs when an instruction modifies the
// rent epoch of an account.
type InstructionError_RentEpochModified struct{}
func (InstructionError_RentEpochModified) Error() string {
return "instruction modified rent epoch of an account"
}
func (InstructionError_RentEpochModified) xx_isInstructionError() {}
// NotEnoughAccountKeys is an error that occurs when an instruction does not
// have enough account keys.
type InstructionError_NotEnoughAccountKeys struct{}
func (InstructionError_NotEnoughAccountKeys) Error() string {
return "insufficient account keys for instruction"
}
func (InstructionError_NotEnoughAccountKeys) xx_isInstructionError() {}
// AccountDataSizeChanged is an error that occurs when a non-system program
// changes the size of an account data.
type InstructionError_AccountDataSizeChanged struct{}
func (InstructionError_AccountDataSizeChanged) Error() string {
return "non-system instruction changed account size"
}
func (InstructionError_AccountDataSizeChanged) xx_isInstructionError() {}
// AccountNotExecutable is an error that occurs when an instruction expects an
// executable account.
type InstructionError_AccountNotExecutable struct{}
func (InstructionError_AccountNotExecutable) Error() string {
return "instruction expected an executable account"
}
func (InstructionError_AccountNotExecutable) xx_isInstructionError() {}
// AccountBorrowFailed is an error that occurs when an instruction fails to
// borrow a reference for an account.
type InstructionError_AccountBorrowFailed struct{}
func (InstructionError_AccountBorrowFailed) Error() string {
return "instruction tries to borrow reference for an account which is already borrowed"
}
func (InstructionError_AccountBorrowFailed) xx_isInstructionError() {}
// AccountBorrowOutstanding is an error that occurs when an account data has an
// outstanding reference after a program's execution.
type InstructionError_AccountBorrowOutstanding struct{}
func (InstructionError_AccountBorrowOutstanding) Error() string {
return "instruction left account with an outstanding borrowed reference"
}
func (InstructionError_AccountBorrowOutstanding) xx_isInstructionError() {}
// The same account was multiply passed to an on-chain program's entrypoint,
// but the program modified them differently. A program can only modify one
// instance of the account because the runtime cannot determine which changes
// to pick or how to merge them if both are modified
type InstructionError_DuplicateAccountOutOfSync struct{}
func (InstructionError_DuplicateAccountOutOfSync) Error() string {
return "instruction modifications of multiply-passed account differ"
}
func (InstructionError_DuplicateAccountOutOfSync) xx_isInstructionError() {}
// Allows on-chain programs to implement program-specific error types and see
// them returned by the Solana runtime. A program-specific error may be any
// type that is represented as or serialized to a u32 integer.
type InstructionError_Custom struct {
Code uint32
Cause error
}
func (v *InstructionError_Custom) Error() string {
if v.Cause != nil {
return v.Cause.Error()
}
return fmt.Sprintf("custom program error: %#x", v.Code)
}
func (v *InstructionError_Custom) Unwrap() error { return v.Cause }
func (*InstructionError_Custom) xx_isInstructionError() {}
// The return value from the program was invalid. Valid errors are either a
// defined builtin error value or a user-defined error in the lower 32 bits.
type InstructionError_InvalidError struct{}
func (InstructionError_InvalidError) Error() string { return "program returned invalid error code" }
func (InstructionError_InvalidError) xx_isInstructionError() {}
// Executable account's data was modified
type InstructionError_ExecutableDataModified struct{}
func (InstructionError_ExecutableDataModified) Error() string {
return "instruction changed executable accounts data"
}
func (InstructionError_ExecutableDataModified) xx_isInstructionError() {}
// Executable account's lamports modified
type InstructionError_ExecutableLamportChange struct{}
func (InstructionError_ExecutableLamportChange) Error() string {
return "instruction changed the balance of a executable account"
}
func (InstructionError_ExecutableLamportChange) xx_isInstructionError() {}
// Executable accounts must be rent exempt
type InstructionError_ExecutableAccountNotRentExempt struct{}
func (InstructionError_ExecutableAccountNotRentExempt) Error() string {
return "executable accounts must be rent exempt"
}
func (InstructionError_ExecutableAccountNotRentExempt) xx_isInstructionError() {}
// Unsupported program id
type InstructionError_UnsupportedProgramId struct{}
func (InstructionError_UnsupportedProgramId) Error() string { return "Unsupported program id" }
func (InstructionError_UnsupportedProgramId) xx_isInstructionError() {}
// Cross-program invocation call depth too deep
type InstructionError_CallDepth struct{}
func (InstructionError_CallDepth) Error() string {
return "Cross-program invocation call depth too deep"
}
func (InstructionError_CallDepth) xx_isInstructionError() {}
// An account required by the instruction is missing
type InstructionError_MissingAccount struct{}
func (InstructionError_MissingAccount) Error() string {
return "An account required by the instruction is missing"
}
func (InstructionError_MissingAccount) xx_isInstructionError() {}
// Cross-program invocation reentrancy not allowed for this instruction
type InstructionError_ReentrancyNotAllowed struct{}
func (InstructionError_ReentrancyNotAllowed) Error() string {
return "Cross-program invocation reentrancy not allowed for this instruction"
}
func (InstructionError_ReentrancyNotAllowed) xx_isInstructionError() {}
// Length of the seed is too long for address generation
type InstructionError_MaxSeedLengthExceeded struct{}
func (InstructionError_MaxSeedLengthExceeded) Error() string {
return "Length of the seed is too long for address generation"
}
func (InstructionError_MaxSeedLengthExceeded) xx_isInstructionError() {}
// Provided seeds do not result in a valid address
type InstructionError_InvalidSeeds struct{}
func (InstructionError_InvalidSeeds) Error() string {
return "Provided seeds do not result in a valid address"
}
func (InstructionError_InvalidSeeds) xx_isInstructionError() {}
// Failed to reallocate account data of this length
type InstructionError_InvalidRealloc struct{}
func (InstructionError_InvalidRealloc) Error() string { return "Failed to reallocate account data" }
func (InstructionError_InvalidRealloc) xx_isInstructionError() {}
// Computational budget exceeded
type InstructionError_ComputationalBudgetExceeded struct{}
func (InstructionError_ComputationalBudgetExceeded) Error() string {
return "Computational budget exceeded"
}
func (InstructionError_ComputationalBudgetExceeded) xx_isInstructionError() {}
// Cross-program invocation with unauthorized signer or writable account
type InstructionError_PrivilegeEscalation struct{}
func (InstructionError_PrivilegeEscalation) Error() string {
return "Cross-program invocation with unauthorized signer or writable account"
}
func (InstructionError_PrivilegeEscalation) xx_isInstructionError() {}
// Failed to create program execution environment
type InstructionError_ProgramEnvironmentSetupFailure struct{}
func (InstructionError_ProgramEnvironmentSetupFailure) Error() string {
return "Failed to create program execution environment"
}
func (InstructionError_ProgramEnvironmentSetupFailure) xx_isInstructionError() {}
// Program failed to complete
type InstructionError_ProgramFailedToComplete struct{}
func (InstructionError_ProgramFailedToComplete) Error() string { return "Program failed to complete" }
func (InstructionError_ProgramFailedToComplete) xx_isInstructionError() {}
// Program failed to compile
type InstructionError_ProgramFailedToCompile struct{}
func (InstructionError_ProgramFailedToCompile) Error() string { return "Program failed to compile" }
func (InstructionError_ProgramFailedToCompile) xx_isInstructionError() {}
// Account is immutable
type InstructionError_Immutable struct{}
func (InstructionError_Immutable) Error() string { return "Account is immutable" }
func (InstructionError_Immutable) xx_isInstructionError() {}
// Incorrect authority provided
type InstructionError_IncorrectAuthority struct{}
func (InstructionError_IncorrectAuthority) Error() string { return "Incorrect authority provided" }
func (InstructionError_IncorrectAuthority) xx_isInstructionError() {}
// An account does not have enough lamports to be rent-exempt
type InstructionError_AccountNotRentExempt struct{}
func (InstructionError_AccountNotRentExempt) Error() string {
return "An account does not have enough lamports to be rent-exempt"
}
func (InstructionError_AccountNotRentExempt) xx_isInstructionError() {}
// Invalid account owner
type InstructionError_InvalidAccountOwner struct{}
func (InstructionError_InvalidAccountOwner) Error() string { return "Invalid account owner" }
func (InstructionError_InvalidAccountOwner) xx_isInstructionError() {}
// Program arithmetic overflowed
type InstructionError_ArithmeticOverflow struct{}
func (InstructionError_ArithmeticOverflow) Error() string { return "Program arithmetic overflowed" }
func (InstructionError_ArithmeticOverflow) xx_isInstructionError() {}
// Unsupported sysvar
type InstructionError_UnsupportedSysvar struct{}
func (InstructionError_UnsupportedSysvar) Error() string { return "Unsupported sysvar" }
func (InstructionError_UnsupportedSysvar) xx_isInstructionError() {}
// Illegal account owner
type InstructionError_IllegalOwner struct{}
func (InstructionError_IllegalOwner) Error() string { return "Provided owner is not allowed" }
func (InstructionError_IllegalOwner) xx_isInstructionError() {}