1
-
2
-
3
1
# Data Drivers Overview
4
2
5
3
In this module, we provide data drivers whose task is to ease communication with Dusk smart contracts
@@ -9,7 +7,7 @@ JavaScript arguments into a form which is understood by Dusk smart contracts,
9
7
and also converting Dusk smart contracts outputs into a form which is understood
10
8
by JavaScript.
11
9
12
- Data drivers do not call Dusk smart contracts. A particular data driver is aware of methods of the corresponding
10
+ Data drivers do not call Dusk smart contracts. A particular data driver is aware of methods of the corresponding
13
11
Dusk smart contract, yet it does not call them.
14
12
15
13
Each data driver has its assigned Dusk smart contract, yet it is important to
@@ -19,12 +17,12 @@ and of their arguments and outputs.
19
17
# Module data-driver
20
18
21
19
Module data-driver contains core code to be used by all drivers. It can be thought of as a framework to
22
- be used by concrete drivers, which are written for particular contracts.
23
- Module data-driver makes it easy for the authors of concrete drivers to create a driver.
20
+ be used by concrete drivers, which are written for particular contracts.
21
+ Module data-driver makes it easy for the authors of concrete drivers to create a driver.
24
22
The authors need just to implement one trait, the complexity is delegated to module data-driver.
25
23
26
- Module data-driver provides functionality which make it easy to call drivers from both Rust and JavaScript.
27
- In order to achieve that it does not use wasm-bindgen, but rather provides a set methods which are easy to call
24
+ Module data-driver provides functionality which make it easy to call drivers from both Rust and JavaScript.
25
+ In order to achieve that it does not use wasm-bindgen, but rather provides a set methods which are easy to call
28
26
from modules written in both languages. The methods are declared with no argument mangling, making them callable
29
27
from within any language which supports "C"-like calling conventions.
30
28
@@ -68,6 +66,7 @@ following parameters:
68
66
out_ptr: *mut u8,
69
67
out_buf_size: usize,
70
68
```
69
+
71
70
In order to pass method name, caller must allocate a buffer, copy the name to it, and pass
72
71
a pointer to the buffer and its length. Similarly, with input data and with output data.
73
72
To allocate a buffer, caller needs to use ` alloc ` method which will return a buffer offset
@@ -88,6 +87,7 @@ There are four methods in this group, so lets consider each one of them in turn:
88
87
### encode_input_fn
89
88
90
89
Parameters:
90
+
91
91
```
92
92
fn_name_ptr: *mut u8,
93
93
fn_name_size: usize,
@@ -99,16 +99,17 @@ Parameters:
99
99
100
100
This method accepts method name and a buffer containing arguments in JSON form.
101
101
On return, it fills out the output buffer with output length (first 4 bytes, as a big-endian 32-bit number),
102
- and then it fills out the subsequent bytes of the buffer with rkyv serialization ready to be used when
102
+ and then it fills out the subsequent bytes of the buffer with rkyv serialization ready to be used when
103
103
making a call to a given smart contract method.
104
104
Caller needs to read first 4 bytes of the output buffer first to know the returned data length.
105
105
Say, first 4 bytes contained number N. The caller then needs to read the remaining N bytes of rkyv
106
- serialization returned. Assuming that the method name passed to ` encode_input_fn ` was M,
106
+ serialization returned. Assuming that the method name passed to ` encode_input_fn ` was M,
107
107
the caller can pass the obtained data to smart contract method M as its arguments.
108
108
109
109
### decode_input_fn
110
110
111
111
Parameters:
112
+
112
113
```
113
114
fn_name_ptr: *mut u8,
114
115
fn_name_size: usize,
@@ -124,6 +125,7 @@ rkyv serialization string into JSON. Other calling details are the same as in `e
124
125
### decode_output_fn
125
126
126
127
Parameters:
128
+
127
129
```
128
130
fn_name_ptr: *mut u8,
129
131
fn_name_size: usize,
@@ -139,6 +141,7 @@ rather than input. Other calling details are the same as in `encode_input_fn` an
139
141
### decode_event
140
142
141
143
Parameters:
144
+
142
145
```
143
146
event_name_ptr: *mut u8,
144
147
event_name_size: usize,
@@ -152,6 +155,7 @@ This method converts event from rkyv-serialized form into JSON. Unlike other arg
152
155
this method accepts event name rather than method name.
153
156
154
157
All the above methods make it possible to:
158
+
155
159
- convert JSON arguments to rkyv bytes ready to be used in smart contract method calls
156
160
- convert rkyv bytes returned by smart contract method calls into JSON
157
161
- convert events emitted by smart contract into JSON
@@ -167,15 +171,15 @@ Method get_last_error() allows obtaining detailed error description when ErrorCo
167
171
Method get_schema() should return JSON schema describing all contract calls. This feature is not used yet
168
172
and in current implementation an empty string is returned.
169
173
170
- Method get_version() returns versions of the driver. Currently, versioning is up to the discretion of
174
+ Method get_version() returns versions of the driver. Currently, versioning is up to the discretion of
171
175
driver's author.
172
176
173
177
## Trait ConvertibleContract - to be used by drivers' creators
174
178
175
179
Fortunately, the above functions with their rather complex parameters are to be used only internally, by this module
176
- (i.e. module data-driver) and by the infrastructure. Regular smart contract authors are dealing
177
- only with a much simplified trait named ` ConvertibleContract ` . The trait is a Rust concept and
178
- its methods are to be implemented in Rust, yet thanks to
180
+ (i.e. module data-driver) and by the infrastructure. Regular smart contract authors are dealing
181
+ only with a much simplified trait named ` ConvertibleContract ` . The trait is a Rust concept and
182
+ its methods are to be implemented in Rust, yet thanks to
179
183
the architecture enabled by the module data-driver, the driver which implements ` ConvertibleContract ` and uses
180
184
module data-driver will provide arguments and return values translations to both JavaScript and Rust users.
181
185
@@ -191,7 +195,7 @@ Smart contract author needs to implement the following methods of trait `Convert
191
195
```
192
196
193
197
As you can see, thanks to the fact that the trait is a Rust concept and confined within the the realm
194
- of a single language, the parameters are much simplified. Module data-driver provides a set of
198
+ of a single language, the parameters are much simplified. Module data-driver provides a set of
195
199
conversion methods which make implementing the trait ConvertibleContract easy.
196
200
To such helper functions, provided by module data-driver, belong:
197
201
@@ -200,7 +204,7 @@ To such helper functions, provided by module data-driver, belong:
200
204
rkyv_to_json
201
205
from_rkyv
202
206
json_to_rkyv_u64
203
- rkyv_to_json_u64
207
+ rkyv_to_json_u64
204
208
json_to_rkyv_pair_u64
205
209
rkyv_to_json_pair_u64
206
210
```
@@ -291,6 +295,7 @@ In such case, example JSON value could be as follows:
291
295
` tCR9c1pQU1jC5QgmRi3JRb2g1Rhtrc6AxT24VQPtMY3wrsuRrnMBMP6wSoKWXH2opKTeCm5aniEG2HH8ATcUHzeWe6814e8qdECGvLLZvhaRKsi7MJgLAA33PiWZ4b6ptNt `
292
296
293
297
### Single object/structural argument
298
+
294
299
In case of a single object argument of a function, a Rust struct, an example JSON representation could be as follows:
295
300
296
301
```
@@ -320,24 +325,29 @@ pub struct Stake {
320
325
signature: DoubleSignature,
321
326
}
322
327
```
328
+
323
329
where StakeKeys is:
330
+
324
331
```
325
332
pub struct StakeKeys {
326
333
pub account: BlsPublicKey,
327
334
pub owner: StakeFundOwner,
328
335
```
336
+
329
337
and DoubleSignature is:
338
+
330
339
```
331
340
pub struct DoubleSignature {
332
341
pub account: BlsSignature,
333
342
pub owner: BlsSignature,
334
343
}
335
344
```
345
+
336
346
As you can see, JSON representation does not include object name, only its named members.
337
347
338
348
### Multiple primitive arguments
339
349
340
- In case of multiple primitive elements, say, a function which, for example, accepts two arguments,
350
+ In case of multiple primitive elements, say, a function which, for example, accepts two arguments,
341
351
say, u64 and u32. An example JSON could look as follows:
342
352
343
353
` [ 22, 33 ] `
@@ -366,10 +376,11 @@ as above, followed by a u32 number, an example JSON representation could be as f
366
376
"owner": "7kP8oaxopsWi7g6kNGtX3PHVekMF8RKRRx74tqoo1xLmh2zGVN2FmJ5EFg7UJV9stk"
367
377
},
368
378
"value": "4014086097495"
369
- },
379
+ },
370
380
33
371
381
]
372
382
```
383
+
373
384
In the above example, we can see JSON representation of a Stake object and a number 33, being passed as two named
374
385
parameters to a smart contract method. Parameter names are ignored in serialization formats, as Dusk smart
375
386
contract methods assume that all input function parameters form a tuple. A tuple is represented as an array in JSON.
0 commit comments