Skip to content

Commit 5438602

Browse files
authored
Merge pull request #96 from casper-network/kara/bring-back-deferred-serialization-changes
Reapply "New fields; added more detailed explanation for variant disc…
2 parents 840cd2b + 2be08dd commit 5438602

File tree

5 files changed

+751
-39
lines changed

5 files changed

+751
-39
lines changed

versioned_docs/version-2.0.0/concepts/serialization/calltable-serialization.md

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ As mentioned before, the `calltable serialization approach` requires serializing
99
- `fields` - field which is an ordered collection of [Field](#field). This collection is serialized as a Vec<Field> in the "regular" `Binary Serialization Standard` schema. The invariants for `fields` are:
1010
- for each f<sub>i</sub>, f<sub>j</sub> given `i` < `j` implies f<sub>i</sub>.index < f<sub>j</sub>.index
1111
- for each f<sub>i</sub>, f<sub>j</sub> given `i` < `j` implies f<sub>i</sub>.offset < f<sub>j</sub>.offset
12-
- `bytes` - field which is an amorphous blob of bytes serialized as `Bytes` in the "regular" `Binary Serialization Standard` schema.
12+
- `bytes` - field which is an amorphous blob of bytes serialized as `Bytes` in the "regular" `Binary Serialization Standard` schema. Bear in mind that this field will be serialized by appending first a `u32` integer (number of bytes) than the raw bytes payload.
1313

1414
A <span id="field">`Field`</span> consists of:
1515

@@ -79,6 +79,9 @@ Once we have the `fields` and `bytes` we can proceed to serialize those in the "
7979
for i in range(0, len(fields)):
8080
bytes_arr += fields[i]["index"].to_bytes(2, byteorder = 'little')
8181
bytes_arr += fields[i]["offset"].to_bytes(4, byteorder = 'little')
82+
concatenated_serialized_fields_len = len(concatenated_serialized_fields)
83+
print(f"{concatenated_serialized_fields_len}")
84+
bytes_arr += concatenated_serialized_fields_len.to_bytes(4, byteorder = 'little')
8285
bytes_arr += concatenated_serialized_fields
8386
return bytes_arr
8487
```
@@ -88,23 +91,23 @@ and once we have all that we can apply the scripts to example:
8891
```python
8992
I = [0, 1, 3, 5]
9093
B = [bytes([0, 1, 255]), bytes([55, 12, 110, 60, 15]), bytes([7, 149, 1]), bytes([55])]
91-
envelope = buildCalltableData(I, B)
94+
envelope = build_calltable_data(I, B)
9295
serialized_calltable_representation = serialize_calltable_representation(envelope["fields"], envelope["bytes"])
9396
print(f"{serialized_calltable_representation.hex()}")
9497
```
9598

9699
which produces:
97100

98101
```
99-
0400000000000000000001000300000003000800000005000b0000000001ff370c6e3c0f07950137
102+
0400000000000000000001000300000003000800000005000b0000000c0000000001ff370c6e3c0f07950137
100103
```
101104

102105
In the above hex:
103-
| Serialized length of `fields` collection | field[0].index | field[0].offset | field[1].index | field[1].offset | field[2].index | field[2].offset | field[3].index | field[3].offset | bytes |
104-
| ---------------------------------------- | -------------- | --------------- | -------------- | --------------- | -------------- | --------------- | -------------- | --------------- | ----- |
105-
| 04000000 | 0000 | 00000000 | 0100 | 03000000 | 0300 | 08000000 | 0500 | 0b000000 | 0001ff370c6e3c0f07950137
106+
| Serialized length of `fields` collection | field[0].index | field[0].offset | field[1].index | field[1].offset | field[2].index | field[2].offset | field[3].index | field[3].offset | number of bytes in `bytes` field | raw bytes of `bytes` field |
107+
| ---------------------------------------- | -------------- | --------------- | -------------- | --------------- | -------------- | --------------- | -------------- | --------------- | ----- | -- |
108+
| 04000000 | 0000 | 00000000 | 0100 | 03000000 | 0300 | 08000000 | 0500 | 0b000000 | 0c000000 | 0001ff370c6e3c0f07950137
106109

107-
This concludes how we construct and byte-serialize an `envelope`. In the next paragraphs we will explain what are the assumptions and conventions when dealing with `struct`s and `enum`s.
110+
This concludes how we construct and byte-serialize an `envelope`. In the next paragraphs we will explain what are the assumptions and conventions when dealing with `struct`s and `tagged-union`s.
108111

109112
## Serializing uniform data structures
110113

@@ -120,15 +123,15 @@ struct A {
120123

121124
In the above example we could assign `a` index `0`, `b` index `1` and `c` index `2`. Knowing this and assuming that we know how to byte-serialize `OtherStruct` we should be able to create an `envelope` for this struct and serialize it in the `calltable` scheme.
122125

123-
## Serializing enums
126+
## Serializing tagged-unions
124127

125-
By `enums` we understand polymorphic, but limited (an instance of an enum can be only one of N known `variants`) data structures that are unions of structures and/or other enums. An enum variant can be:
128+
By `tagged-union` we understand polymorphic, but limited (an instance of an tagged-union can be only one of N known `variants`) data structures that are unions of structures and/or other tagged-unions. An tagged-union variant can be:
126129

127130
- empty (tag variant)
128131
- a struct
129-
- a nested enum
132+
- a nested tagged-union
130133

131-
As mentioned, there is a polymorphic aspect to these kinds of enums and we handle them by convention - `serialization index` `0` is always reserved for a 1 byte discriminator number which defines which enum variant is being serialized, the next indices are used to serialize the fields of specific variants (for empty tag variants there will be no more indices). So, given an enum:
134+
As mentioned, there is a polymorphic aspect to these kinds of tagged-union and we handle them by convention - `serialization index` `0` is always reserved for a 1 byte discriminator number which defines which tagged-union variant is being serialized. The value of this specific pseudo-field will be called `variant discriminator`. Subsequent indices are used to serialize the fields of specific variants (for empty tag variants there will be no more indices). So, given an example tagged-union (implemented in rust, rust equivalent of tagged-union is `enum`):
132135

133136
```rust
134137
enum X {
@@ -138,13 +141,13 @@ As mentioned, there is a polymorphic aspect to these kinds of enums and we handl
138141
}
139142
```
140143

141-
First we need to chose variant discriminator values for each of the enum variants, let's select:
144+
First we need to chose variant discriminator values for each of the tagged-union variants, let's select:
142145

143146
- if variant `A` - the variant discriminator will be `0`
144147
- if variant `B` - the variant discriminator will be `1`
145148
- if variant `C` - the variant discriminator will be `2`
146149

147-
Again, as with fields in `Serializing enums` the variant discriminator values don't need to start from `0` and don't need to be contiguous, but that is our convention and any "holes" in the definition would indicate a retired enum variant.
150+
Again, as with fields in `Serializing tagged-unions` the variant discriminator values does not need to start from `0` and does not need to be contiguous, but that is our convention and any "discontinuities" in the value set for variant disciminator would indicate a retired tagged-union variant or variants.
148151

149152
Next we need to assign field `serialization indices` for each variant:
150153

@@ -157,8 +160,8 @@ Next we need to assign field `serialization indices` for each variant:
157160
- `2` for the second tuple element (of type u32),
158161
- `3` for the second tuple element (of type u64),
159162

160-
As you can see, `serialization indices` for fields need to be unique in scope of a particular enum variant.
161-
Knowing the above, let's see how the `I` and `B` collections would look like for different instances of this enum:
163+
As you can see, `serialization indices` for fields need to be unique in scope of a particular tagged-union variant.
164+
Knowing the above, let's see how the `I` and `B` collections would look like for different instances of this tagged-union:
162165

163166
- when serializing variant `X::A` (assuming python notation):
164167
```python

0 commit comments

Comments
 (0)