198 lines
4.4 KiB
Markdown
198 lines
4.4 KiB
Markdown
# SSZ, generic tests
|
|
|
|
This set of test-suites provides general testing for SSZ:
|
|
to decode any container/list/vector/other type from binary data, encode it back, and compute the hash-tree-root.
|
|
|
|
This test collection for general-purpose SSZ is experimental.
|
|
The `ssz_static` suite is the required minimal support for SSZ, and should be prioritized.
|
|
|
|
The `ssz_generic` tests are split up into different handler, each specialized into a SSZ type:
|
|
|
|
- Vectors
|
|
- `basic_vector`
|
|
- `complex_vector` *not supported yet*
|
|
- List
|
|
- `basic_list` *not supported yet*
|
|
- `complex_list` *not supported yet*
|
|
- Bitfields
|
|
- `bitvector`
|
|
- `bitlist`
|
|
- Basic types
|
|
- `boolean`
|
|
- `uints`
|
|
- Containers
|
|
- `containers`
|
|
|
|
|
|
## Format
|
|
|
|
For each type, a `valid` and an `invalid` suite is implemented.
|
|
The cases have the same format, but those in the `invalid` suite only declare a subset of the data a test in the `valid` declares.
|
|
|
|
Each of the handlers encodes the SSZ type declaration in the file-name. See [Type Declarations](#type-declarations).
|
|
|
|
### `valid`
|
|
|
|
Valid has 3 parts: `meta.yaml`, `serialized.ssz`, `value.yaml`
|
|
|
|
### `meta.yaml`
|
|
|
|
Valid ssz objects can have a hash-tree-root, and for some types also a signing-root.
|
|
The expected roots are encoded into the metadata yaml:
|
|
|
|
```yaml
|
|
root: Bytes32 -- Hash-tree-root of the object
|
|
signing_root: Bytes32 -- Signing-root of the object
|
|
```
|
|
|
|
The `Bytes32` is encoded as a string, hexadecimal encoding, prefixed with `0x`.
|
|
|
|
### `serialized.ssz`
|
|
|
|
The serialized form of the object, as raw SSZ bytes.
|
|
|
|
### `value.yaml`
|
|
|
|
The object, encoded as a YAML structure. Using the same familiar encoding as YAML data in the other test suites.
|
|
|
|
### Conditions
|
|
|
|
The conditions are the same for each type:
|
|
|
|
- Encoding: After encoding the given `value` object, the output should match `serialized`.
|
|
- Decoding: After decoding the given `serialized` bytes, it should match the `value` object.
|
|
- Hash-tree-root: the root should match the root declared in the metadata.
|
|
- Signing-root: if present in metadata, the signing root of the object should match the container.
|
|
|
|
## `invalid`
|
|
|
|
Test cases in the `invalid` suite only include the `serialized.ssz`
|
|
|
|
#### Condition
|
|
|
|
Unlike the `valid` suite, invalid encodings do not have any `value` or hash tree root.
|
|
The `serialized` data should simply not be decoded without raising an error.
|
|
|
|
Note that for some type declarations in the invalid suite, the type itself may technically be invalid.
|
|
This is a valid way of detecting `invalid` data too. E.g. a 0-length basic vector.
|
|
|
|
|
|
## Type declarations
|
|
|
|
Most types are not as static, and can reasonably be constructed during test runtime from the test case name.
|
|
Formats are listed below.
|
|
|
|
For each test case, an additional `_{extra...}` may be appended to the name,
|
|
where `{extra...}` contains a human readable indication of the test case contents for debugging purposes.
|
|
|
|
### `basic_vector`
|
|
|
|
```
|
|
Template:
|
|
|
|
vec_{element type}_{length}
|
|
|
|
Data:
|
|
|
|
{element type}: bool, uint8, uint16, uint32, uint64, uint128, uint256
|
|
|
|
{length}: an unsigned integer
|
|
```
|
|
|
|
|
|
### `bitlist`
|
|
|
|
```
|
|
Template:
|
|
|
|
bitlist_{limit}
|
|
|
|
Data:
|
|
|
|
{limit}: the list limit, in bits, of the bitlist. Does not include the length-delimiting bit in the serialized form.
|
|
```
|
|
|
|
|
|
### `bitvector`
|
|
|
|
```
|
|
Template:
|
|
|
|
bitvec_{length}
|
|
|
|
Data:
|
|
|
|
{length}: the length, in bits, of the bitvector.
|
|
```
|
|
|
|
### `boolean`
|
|
|
|
A boolean has no type variations. Instead, file names just plainly describe the contents for debugging.
|
|
|
|
### `uints`
|
|
|
|
```
|
|
Template:
|
|
|
|
uint_{size}
|
|
|
|
Data:
|
|
|
|
{size}: the uint size: 8, 16, 32, 64, 128 or 256.
|
|
```
|
|
|
|
### `containers`
|
|
|
|
Containers are more complicated than the other types. Instead, a set of pre-defined container structures is referenced:
|
|
|
|
```
|
|
Template:
|
|
|
|
{container name}
|
|
|
|
Data:
|
|
|
|
{container name}: Any of the container names listed below (exluding the `(Container)` python super type)
|
|
```
|
|
|
|
```python
|
|
|
|
class SingleFieldTestStruct(Container):
|
|
A: byte
|
|
|
|
|
|
class SmallTestStruct(Container):
|
|
A: uint16
|
|
B: uint16
|
|
|
|
|
|
class FixedTestStruct(Container):
|
|
A: uint8
|
|
B: uint64
|
|
C: uint32
|
|
|
|
|
|
class VarTestStruct(Container):
|
|
A: uint16
|
|
B: List[uint16, 1024]
|
|
C: uint8
|
|
|
|
|
|
class ComplexTestStruct(Container):
|
|
A: uint16
|
|
B: List[uint16, 128]
|
|
C: uint8
|
|
D: Bytes[256]
|
|
E: VarTestStruct
|
|
F: Vector[FixedTestStruct, 4]
|
|
G: Vector[VarTestStruct, 2]
|
|
|
|
|
|
class BitsStruct(Container):
|
|
A: Bitlist[5]
|
|
B: Bitvector[2]
|
|
C: Bitvector[1]
|
|
D: Bitlist[6]
|
|
E: Bitvector[8]
|
|
```
|