clvm-traits 0.42.1

Traits for encoding and decoding CLVM objects.
Documentation
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
As well as the built-in implementations, this library exposes two derive macros
for implementing the `ToClvm` and `FromClvm` traits on structs and enums.
These macros can be used with both named and unnamed structs and enum variants.

## Representations

There are multiple ways to encode a sequence of fields in either a struct or an enum variant.
These are referred to as representations and are specified using the `#[clvm(...)]` attribute.
Below are examples of derive macros using each of these representations.
Pick whichever representation fits your use-case the best.

Note that the syntax `(A . B)` represents a cons-pair with two values, `A` and `B`.
This is how non-atomic values are structured in CLVM.

### Proper List

This represents values in a nil terminated series of nested cons-pairs.

Note that if you mark the last field to [consume the rest of the list](#consume-the-rest), there is no nil terminator.

For example, with the list `[A, B, C]`, we build the list in reverse:

- Start with the nil terminator `()`
- Create the first cons pair `(C . ())`
- Then continue on with `(B . (C . ()))`
- Finally, the list is represented as `(A . (B . (C . ())))`

```rust
use clvmr::Allocator;
use clvm_traits::{ToClvm, FromClvm};

#[derive(Debug, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(proper_list)]
struct Tiers {
    high: u8,
    medium: u8,
    low: u8,
}

// The CLVM representation for this is `(10 5 1)`.
// It can also be written as `(10 . (5 . (1 . ())))`.
let value = Tiers {
    high: 10,
    medium: 5,
    low: 1,
};

let a = &mut Allocator::new();
let ptr = value.to_clvm(a).unwrap();
assert_eq!(Tiers::from_clvm(a, ptr).unwrap(), value);
```

### List

The list representation is the same as proper list, except it does not check the nil terminator when parsing.
This allows it to be lenient to additional parameters that are in the CLVM object, which is especially useful
for preventing errors when parsing on-chain solutions and output conditions, where you wouldn't want strictness.
This is because puzzles often don't enforce additional solution parameters, and consensus allows additional
parameters to leave the door open for soft forks in the future.

### Curry

This represents the argument part of a curried CLVM program.
In Chia, currying commits to and partially applies some of the arguments of a program, without calling it.

The arguments are quoted and terminated with `1`, which is how partial application is implemented in CLVM.
Note that if you mark the last field to [consume the rest of the arguments](#consume-the-rest), there is no `1` terminator.

For example, the curried arguments `[A, B, C]` are encoded as `(c (q . A) (c (q . B) (c (q . C) 1)))`.

You can read more about currying on the [Chia blockchain documentation](https://docs.chia.net/guides/chialisp-currying).

The following example is for demonstration purposes only:

```rust
use clvmr::Allocator;
use clvm_traits::{ToClvm, FromClvm};

#[derive(Debug, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(curry)]
struct PuzzleArgs {
    code_to_unlock: u32,
    verification_level: u8,
}

// The CLVM representation for this is `(c (q . 4328714) (c (q . 5) 1))`.
let args = PuzzleArgs {
    code_to_unlock: 4328714,
    verification_level: 5,
};

let a = &mut Allocator::new();
let ptr = args.to_clvm(a).unwrap();
assert_eq!(PuzzleArgs::from_clvm(a, ptr).unwrap(), args);
```

### Transparent

If you want a struct to have the same CLVM representation as its inner struct (a newtype), you can use the `transparent` representation.

```rust
use clvmr::Allocator;
use clvm_traits::{ToClvm, FromClvm};

#[derive(Debug, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(transparent)]
struct CustomString(String);

// The CLVM representation for this is the same as the string itself.
// So `"Hello"` in this case.
let string = CustomString("Hello".to_string());

let a = &mut Allocator::new();
let ptr = string.to_clvm(a).unwrap();
assert_eq!(CustomString::from_clvm(a, ptr).unwrap(), string);
```

## Optional Fields

You can only mark the last field in a struct or enum variant as optional.

This restriction is in place because if you were able to have multiple optional fields,
or an optional field that isn't at the end, it would be ambiguous.

### Optional Value

You can set a field as optional by marking it as `#[clvm(default)]`.
If the field isn't present when deserializing, it will default to the `Default` implementation of the type.
When serializing, it will check if it's equal to the default and omit it if so.

```rust
use clvmr::Allocator;
use clvm_traits::{ToClvm, FromClvm};

#[derive(Debug, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(list)]
struct Person {
    name: String,
    #[clvm(default)]
    email: Option<String>,
}

// The CLVM representation of this is `("Bob" "bob@example.com")`.
// If `email` had been set to `None`, the representation would have just been `("Bob")`.
let person = Person {
    name: "Bob".to_string(),
    email: Some("bob@example.com".to_string()),
};

let a = &mut Allocator::new();
let ptr = person.to_clvm(a).unwrap();
assert_eq!(Person::from_clvm(a, ptr).unwrap(), person);
```

### Default Value

You can also specify the default value to check against manually.
This is useful if you want to override the `Default` trait, or if the `Default` trait isn't implemented.

```rust
use clvmr::Allocator;
use clvm_traits::{ToClvm, FromClvm};

#[derive(Debug, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(list)]
struct Person {
    name: String,
    #[clvm(default = 18)]
    age: u8,
}

// The CLVM representation for this is `("Bob" 24)`.
// If `age` had been set to `18`, the representation would have been just `("Bob")`.
let person = Person {
    name: "Bob".to_string(),
    age: 24,
};

let a = &mut Allocator::new();
let ptr = person.to_clvm(a).unwrap();
assert_eq!(Person::from_clvm(a, ptr).unwrap(), person);
```

## Consume the Rest

You can consume the rest of the list items (or curried arguments, if using the `curry` representation) by using `#[clvm(rest)]`.
This is useful for types which are represented compactly, without a nil terminator. Or for extending a list of arguments with another.
You can also use it if you want to lazily parse the rest later.

Here's a simple example of a compact representation:

```rust
use clvmr::Allocator;
use clvm_traits::{ToClvm, FromClvm};

#[derive(Debug, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(list)]
struct Point {
    x: i32,
    #[clvm(rest)]
    y: i32,
}

// The CLVM representation of this is `(5 . 2)` (with no nil terminator).
let point = Point {
    x: 5,
    y: 2,
};

let a = &mut Allocator::new();
let ptr = point.to_clvm(a).unwrap();
assert_eq!(Point::from_clvm(a, ptr).unwrap(), point);
```

And here's an example of lazily parsing the rest later:

```rust
use clvmr::{Allocator, NodePtr};
use clvm_traits::{ToClvm, FromClvm};

#[derive(Debug, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(list)]
struct Items<T> {
    first: String,
    #[clvm(rest)]
    rest: T,
}

// The CLVM representation of this is `("First Item" 1 2 3 4 5)`.
// Notice how the list is not a separate argument, but rather the rest of the arguments.
let items = Items {
    first: "First Item".to_string(),
    rest: [1, 2, 3, 4, 5],
};

let a = &mut Allocator::new();
let ptr = items.to_clvm(a).unwrap();

// We parse `("First Item" . <rest>)`
let items = Items::<NodePtr>::from_clvm(a, ptr).unwrap();
assert_eq!(items.first, "First Item".to_string());

// Then parse rest into a separate list of `(1 2 3 4 5)`.
let rest: [u8; 5] = FromClvm::from_clvm(a, items.rest).unwrap();
assert_eq!(rest, [1, 2, 3, 4, 5]);
```

## Enums

In Rust, enums contain a discriminant, a value used to distinguish between each variant of the enum.
In most cases, the CLVM representation of the enum will need to contain this discriminant as the first argument.
For convenience, this is the behavior when deriving `ToClvm` and `FromClvm` for enums by default.

### Simple Example

In this example, since the `atom` representation, the variants will be encoded as an integer.
Discriminants default to the `isize` type and the first value is `0`. Subsequent values are incremented by `1` by default.

```rust
use clvmr::Allocator;
use clvm_traits::{ToClvm, FromClvm};

#[derive(Debug, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(atom)]
enum Status {
    Pending,
    Completed,
}

// The CLVM representation of this is just `0`.
let status = Status::Pending;

let a = &mut Allocator::new();
let ptr = status.to_clvm(a).unwrap();
assert_eq!(Status::from_clvm(a, ptr).unwrap(), status);
```

### Custom Discriminator

It's possible to override both the type of the discriminator, and the value.
The `#[repr(...)]` attribute is used by the Rust compiler to allow overriding the discriminator type.
As such, this attribute is also used to change the underlying type used to serialize and deserialize discriminator values.

```rust
use clvmr::Allocator;
use clvm_traits::{ToClvm, FromClvm};

#[derive(Debug, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(atom)]
#[repr(u8)]
enum Status {
    Pending = 36,
    Completed = 42,
}

// The CLVM representation of this is `36`.
let status = Status::Pending;

let a = &mut Allocator::new();
let ptr = status.to_clvm(a).unwrap();
assert_eq!(Status::from_clvm(a, ptr).unwrap(), status);
```

### Variant Fields

Of course, you can also include fields on enum variants, and they will be serialized after the discriminator accordingly.
It's also possible to override the representation of an individual variant, as if it were a standalone struct.

```rust
use clvmr::Allocator;
use clvm_traits::{ToClvm, FromClvm};

#[derive(Debug, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(list)]
enum SpendMode {
    AppendValue { value: i32 },
    ClearValues,
}

// The CLVM representation of this is `(42)`.
let mode = SpendMode::AppendValue {
    value: 42
};

let a = &mut Allocator::new();
let ptr = mode.to_clvm(a).unwrap();
assert_eq!(SpendMode::from_clvm(a, ptr).unwrap(), mode);
```

### Untagged Enums

Often, the discriminator isn't necessary to encode, and you'd prefer to try to match each variant in order until one matches.
This is what `#[clvm(untagged)]` allows you to do.

Note that if there is any ambiguity, the first variant which matches a value will be the resulting value.
For example, if both `A` and `B` are in that order and are the same type, if you serialize a value of `B`, it will be deserialized as `A`.

```rust
use clvmr::Allocator;
use clvm_traits::{ToClvm, FromClvm};

#[derive(Debug, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(list, untagged)]
enum Either {
    ShortList([i32; 4]),
    ExtendedList([i32; 16]),
}

// The CLVM representation of this is `((42 42 42 42))`.
let value = Either::ShortList([42; 4]);

let a = &mut Allocator::new();
let ptr = value.to_clvm(a).unwrap();
assert_eq!(Either::from_clvm(a, ptr).unwrap(), value);
```

## Constant Values

Sometimes you may want to include constants inside of a struct without actually exposing them as fields.
It's possible to do this with `#[clvm(constant = ...)]`, however you must use an attribute macro to remove the constant fields.

This has to be done in the proper order, or it will not work.

The order is as follows:

- Derive `ToClvm` and `FromClvm`, so that the constant fields are serialized and deserialized properly.
- Use `#[apply_constants]` to remove them from the actual struct or enum, but keep them in the encoded output.
- Add any other derives you want after, so they don't see the constant fields.
- Write any `#[clvm(...)]` options you want to use.

Here is an example of this:

```rust
use clvmr::Allocator;
use clvm_traits::{apply_constants, ToClvm, FromClvm};

#[derive(ToClvm, FromClvm)]
#[apply_constants]
#[derive(Debug, PartialEq, Eq)]
#[clvm(list)]
struct CustomTerminator {
    value: u32,
    #[clvm(constant = 42, rest)]
    terminator: u8,
}

// The CLVM representation of this is `(100 . 42)`.
let value = CustomTerminator {
    value: 100,
};

let a = &mut Allocator::new();
let ptr = value.to_clvm(a).unwrap();
assert_eq!(CustomTerminator::from_clvm(a, ptr).unwrap(), value);
```

## Crate Name

You can override the name of the `clvm_traits` crate used within the macros:

```rust
use clvmr::Allocator;
use clvm_traits::{self as renamed_clvm_traits, ToClvm, FromClvm};

#[derive(Debug, PartialEq, Eq, ToClvm, FromClvm)]
#[clvm(list, crate_name = renamed_clvm_traits)]
struct Example;
```