forked from stellar/stellar-xdr
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Stellar-contract.x
282 lines (238 loc) · 8.11 KB
/
Stellar-contract.x
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
// Copyright 2022 Stellar Development Foundation and contributors. Licensed
// under the Apache License, Version 2.0. See the COPYING file at the root
// of this distribution or at http://www.apache.org/licenses/LICENSE-2.0
% #include "xdr/Stellar-types.h"
namespace stellar
{
// We fix a maximum of 128 value types in the system for two reasons: we want to
// keep the codes relatively small (<= 8 bits) when bit-packing values into a
// u64 at the environment interface level, so that we keep many bits for
// payloads (small strings, small numeric values, object handles); and then we
// actually want to go one step further and ensure (for code-size) that our
// codes fit in a single ULEB128-code byte, which means we can only use 7 bits.
//
// We also reserve several type codes from this space because we want to _reuse_
// the SCValType codes at the environment interface level (or at least not
// exceed its number-space) but there are more types at that level, assigned to
// optimizations/special case representations of values abstract at this level.
enum SCValType
{
SCV_BOOL = 0,
SCV_VOID = 1,
SCV_ERROR = 2,
// 32 bits is the smallest type in WASM or XDR; no need for u8/u16.
SCV_U32 = 3,
SCV_I32 = 4,
// 64 bits is naturally supported by both WASM and XDR also.
SCV_U64 = 5,
SCV_I64 = 6,
// Time-related u64 subtypes with their own functions and formatting.
SCV_TIMEPOINT = 7,
SCV_DURATION = 8,
// 128 bits is naturally supported by Rust and we use it for Soroban
// fixed-point arithmetic prices / balances / similar "quantities". These
// are represented in XDR as a pair of 2 u64s.
SCV_U128 = 9,
SCV_I128 = 10,
// 256 bits is the size of sha256 output, ed25519 keys, and the EVM machine
// word, so for interop use we include this even though it requires a small
// amount of Rust guest and/or host library code.
SCV_U256 = 11,
SCV_I256 = 12,
// Bytes come in 3 flavors, 2 of which have meaningfully different
// formatting and validity-checking / domain-restriction.
SCV_BYTES = 13,
SCV_STRING = 14,
SCV_SYMBOL = 15,
// Vecs and maps are just polymorphic containers of other ScVals.
SCV_VEC = 16,
SCV_MAP = 17,
// Address is the universal identifier for contracts and classic
// accounts.
SCV_ADDRESS = 18,
// The following are the internal SCVal variants that are not
// exposed to the contracts.
SCV_CONTRACT_INSTANCE = 19,
// SCV_LEDGER_KEY_CONTRACT_INSTANCE and SCV_LEDGER_KEY_NONCE are unique
// symbolic SCVals used as the key for ledger entries for a contract's
// instance and an address' nonce, respectively.
SCV_LEDGER_KEY_CONTRACT_INSTANCE = 20,
SCV_LEDGER_KEY_NONCE = 21
};
enum SCErrorType
{
SCE_CONTRACT = 0, // Contract-specific, user-defined codes.
SCE_WASM_VM = 1, // Errors while interpreting WASM bytecode.
SCE_CONTEXT = 2, // Errors in the contract's host context.
SCE_STORAGE = 3, // Errors accessing host storage.
SCE_OBJECT = 4, // Errors working with host objects.
SCE_CRYPTO = 5, // Errors in cryptographic operations.
SCE_EVENTS = 6, // Errors while emitting events.
SCE_BUDGET = 7, // Errors relating to budget limits.
SCE_VALUE = 8, // Errors working with host values or SCVals.
SCE_AUTH = 9 // Errors from the authentication subsystem.
};
enum SCErrorCode
{
SCEC_ARITH_DOMAIN = 0, // Some arithmetic was undefined (overflow, divide-by-zero).
SCEC_INDEX_BOUNDS = 1, // Something was indexed beyond its bounds.
SCEC_INVALID_INPUT = 2, // User provided some otherwise-bad data.
SCEC_MISSING_VALUE = 3, // Some value was required but not provided.
SCEC_EXISTING_VALUE = 4, // Some value was provided where not allowed.
SCEC_EXCEEDED_LIMIT = 5, // Some arbitrary limit -- gas or otherwise -- was hit.
SCEC_INVALID_ACTION = 6, // Data was valid but action requested was not.
SCEC_INTERNAL_ERROR = 7, // The host detected an error in its own logic.
SCEC_UNEXPECTED_TYPE = 8, // Some type wasn't as expected.
SCEC_UNEXPECTED_SIZE = 9 // Something's size wasn't as expected.
};
// Smart contract errors are split into a type (SCErrorType) and a code. When an
// error is of type SCE_CONTRACT it carries a user-defined uint32 code that
// Soroban assigns no specific meaning to. In all other cases, the type
// specifies a subsystem of the Soroban host where the error originated, and the
// accompanying code is an SCErrorCode, each of which specifies a slightly more
// precise class of errors within that subsystem.
//
// Error types and codes are not maximally precise; there is a tradeoff between
// precision and flexibility in the implementation, and the granularity here is
// chosen to be adequate for most purposes while not placing a burden on future
// system evolution and maintenance. When additional precision is needed for
// debugging, Soroban can be run with diagnostic events enabled.
union SCError switch (SCErrorType type)
{
case SCE_CONTRACT:
uint32 contractCode;
case SCE_WASM_VM:
case SCE_CONTEXT:
case SCE_STORAGE:
case SCE_OBJECT:
case SCE_CRYPTO:
case SCE_EVENTS:
case SCE_BUDGET:
case SCE_VALUE:
case SCE_AUTH:
SCErrorCode code;
};
struct UInt128Parts {
uint64 hi;
uint64 lo;
};
// A signed int128 has a high sign bit and 127 value bits. We break it into a
// signed high int64 (that carries the sign bit and the high 63 value bits) and
// a low unsigned uint64 that carries the low 64 bits. This will sort in
// generated code in the same order the underlying int128 sorts.
struct Int128Parts {
int64 hi;
uint64 lo;
};
struct UInt256Parts {
uint64 hi_hi;
uint64 hi_lo;
uint64 lo_hi;
uint64 lo_lo;
};
// A signed int256 has a high sign bit and 255 value bits. We break it into a
// signed high int64 (that carries the sign bit and the high 63 value bits) and
// three low unsigned `uint64`s that carry the lower bits. This will sort in
// generated code in the same order the underlying int256 sorts.
struct Int256Parts {
int64 hi_hi;
uint64 hi_lo;
uint64 lo_hi;
uint64 lo_lo;
};
enum ContractExecutableType
{
CONTRACT_EXECUTABLE_WASM = 0,
CONTRACT_EXECUTABLE_STELLAR_ASSET = 1
};
union ContractExecutable switch (ContractExecutableType type)
{
case CONTRACT_EXECUTABLE_WASM:
Hash wasm_hash;
case CONTRACT_EXECUTABLE_STELLAR_ASSET:
void;
};
enum SCAddressType
{
SC_ADDRESS_TYPE_ACCOUNT = 0,
SC_ADDRESS_TYPE_CONTRACT = 1
};
union SCAddress switch (SCAddressType type)
{
case SC_ADDRESS_TYPE_ACCOUNT:
AccountID accountId;
case SC_ADDRESS_TYPE_CONTRACT:
Hash contractId;
};
%struct SCVal;
%struct SCMapEntry;
const SCSYMBOL_LIMIT = 32;
typedef SCVal SCVec<>;
typedef SCMapEntry SCMap<>;
typedef opaque SCBytes<>;
typedef string SCString<>;
typedef string SCSymbol<SCSYMBOL_LIMIT>;
struct SCNonceKey {
int64 nonce;
};
struct SCContractInstance {
ContractExecutable executable;
SCMap* storage;
};
union SCVal switch (SCValType type)
{
case SCV_BOOL:
bool b;
case SCV_VOID:
void;
case SCV_ERROR:
SCError error;
case SCV_U32:
uint32 u32;
case SCV_I32:
int32 i32;
case SCV_U64:
uint64 u64;
case SCV_I64:
int64 i64;
case SCV_TIMEPOINT:
TimePoint timepoint;
case SCV_DURATION:
Duration duration;
case SCV_U128:
UInt128Parts u128;
case SCV_I128:
Int128Parts i128;
case SCV_U256:
UInt256Parts u256;
case SCV_I256:
Int256Parts i256;
case SCV_BYTES:
SCBytes bytes;
case SCV_STRING:
SCString str;
case SCV_SYMBOL:
SCSymbol sym;
// Vec and Map are recursive so need to live
// behind an option, due to xdrpp limitations.
case SCV_VEC:
SCVec *vec;
case SCV_MAP:
SCMap *map;
case SCV_ADDRESS:
SCAddress address;
// Special SCVals reserved for system-constructed contract-data
// ledger keys, not generally usable elsewhere.
case SCV_LEDGER_KEY_CONTRACT_INSTANCE:
void;
case SCV_LEDGER_KEY_NONCE:
SCNonceKey nonce_key;
case SCV_CONTRACT_INSTANCE:
SCContractInstance instance;
};
struct SCMapEntry
{
SCVal key;
SCVal val;
};
}