@@ -29,15 +29,15 @@ use rgb::validation::Scripts;
29
29
use rgb:: {
30
30
validation, AltLayer1 , AltLayer1Set , AssignmentType , Assignments , ContractId , ExposedSeal ,
31
31
Genesis , GenesisSeal , GlobalState , GraphSeal , Identity , Input , Layer1 , MetadataError , Opout ,
32
- OwnedStateSchema , Schema , State , Transition , TransitionType , TypedAssigns , XChain , XOutpoint ,
32
+ Schema , State , Transition , TransitionType , TypedAssigns , XChain , XOutpoint ,
33
33
} ;
34
34
use rgbcore:: { GlobalStateSchema , GlobalStateType , MetaType , Metadata , ValencyType } ;
35
35
use strict_encoding:: { FieldName , SerializeError , StrictSerialize } ;
36
36
use strict_types:: { decode, SemId , TypeSystem } ;
37
37
38
38
use crate :: containers:: { BuilderSeal , ContainerVer , Contract , ValidConsignment } ;
39
39
use crate :: interface:: resolver:: DumbResolver ;
40
- use crate :: interface:: { Iface , IfaceImpl , TransitionIface } ;
40
+ use crate :: interface:: { Iface , IfaceImpl , StateCalc , StateCalcError , TransitionIface } ;
41
41
use crate :: Outpoint ;
42
42
43
43
#[ derive( Clone , Eq , PartialEq , Debug , Display , Error , From ) ]
@@ -68,19 +68,7 @@ pub enum BuilderError {
68
68
/// state `{0}` provided to the builder has invalid type.
69
69
InvalidStateType ( AssignmentType ) ,
70
70
71
- /// asset tag for state `{0}` must be added before any fungible state of
72
- /// the same type.
73
- AssetTagMissed ( AssignmentType ) ,
74
-
75
- /// asset tag for state `{0}` was already automatically created. Please call
76
- /// `add_asset_tag` before adding any fungible state to the builder.
77
- AssetTagAutomatic ( AssignmentType ) ,
78
-
79
- /// state data for state type `{0}` are invalid: asset tag doesn't match the
80
- /// tag defined by the contract.
81
- AssetTagInvalid ( AssignmentType ) ,
82
-
83
- /// interface doesn't specifies default operation name, thus an explicit
71
+ /// interface doesn't specify default operation name, thus an explicit
84
72
/// operation type must be provided with `set_operation_type` method.
85
73
NoOperationSubtype ,
86
74
@@ -90,6 +78,10 @@ pub enum BuilderError {
90
78
/// {0} is not supported by the contract genesis.
91
79
InvalidLayer1 ( Layer1 ) ,
92
80
81
+ #[ from]
82
+ #[ display( inner) ]
83
+ Calc ( StateCalcError ) ,
84
+
93
85
#[ from]
94
86
#[ display( inner) ]
95
87
StrictEncode ( SerializeError ) ,
@@ -226,13 +218,13 @@ impl ContractBuilder {
226
218
227
219
pub fn add_owned_state_raw (
228
220
mut self ,
229
- name : impl Into < FieldName > ,
221
+ type_id : AssignmentType ,
230
222
seal : impl Into < BuilderSeal < GenesisSeal > > ,
231
223
state : State ,
232
224
) -> Result < Self , BuilderError > {
233
225
let seal = seal. into ( ) ;
234
226
self . check_layer1 ( seal. layer1 ( ) ) ?;
235
- self . builder = self . builder . add_owned_state_raw ( name , seal, state) ?;
227
+ self . builder = self . builder . add_owned_state_raw ( type_id , seal, state) ?;
236
228
Ok ( self )
237
229
}
238
230
@@ -306,13 +298,15 @@ impl ContractBuilder {
306
298
}
307
299
}
308
300
309
- #[ derive( Clone , Debug ) ]
301
+ #[ derive( Debug ) ]
310
302
pub struct TransitionBuilder {
311
303
contract_id : ContractId ,
312
304
builder : OperationBuilder < GraphSeal > ,
313
305
nonce : u64 ,
314
306
transition_type : TransitionType ,
315
307
inputs : TinyOrdMap < Input , State > ,
308
+ // TODO: Remove option once we have blank builder
309
+ calc : Option < StateCalc > ,
316
310
}
317
311
318
312
impl TransitionBuilder {
@@ -323,7 +317,7 @@ impl TransitionBuilder {
323
317
iimpl : IfaceImpl ,
324
318
types : TypeSystem ,
325
319
) -> Self {
326
- Self :: with ( contract_id, iface, schema, iimpl, TransitionType :: BLANK , types)
320
+ Self :: with ( contract_id, iface, schema, iimpl, TransitionType :: BLANK , types, None )
327
321
}
328
322
329
323
pub fn default_transition (
@@ -332,13 +326,15 @@ impl TransitionBuilder {
332
326
schema : Schema ,
333
327
iimpl : IfaceImpl ,
334
328
types : TypeSystem ,
329
+ scripts : Scripts ,
335
330
) -> Result < Self , BuilderError > {
336
331
let transition_type = iface
337
332
. default_operation
338
333
. as_ref ( )
339
334
. and_then ( |name| iimpl. transition_type ( name) )
340
335
. ok_or ( BuilderError :: NoOperationSubtype ) ?;
341
- Ok ( Self :: with ( contract_id, iface, schema, iimpl, transition_type, types) )
336
+ let calc = StateCalc :: new ( scripts, iimpl. state_abi ) ;
337
+ Ok ( Self :: with ( contract_id, iface, schema, iimpl, transition_type, types, Some ( calc) ) )
342
338
}
343
339
344
340
pub fn named_transition (
@@ -348,12 +344,14 @@ impl TransitionBuilder {
348
344
iimpl : IfaceImpl ,
349
345
transition_name : impl Into < FieldName > ,
350
346
types : TypeSystem ,
347
+ scripts : Scripts ,
351
348
) -> Result < Self , BuilderError > {
352
349
let transition_name = transition_name. into ( ) ;
353
350
let transition_type = iimpl
354
351
. transition_type ( & transition_name)
355
352
. ok_or ( BuilderError :: TransitionNotFound ( transition_name) ) ?;
356
- Ok ( Self :: with ( contract_id, iface, schema, iimpl, transition_type, types) )
353
+ let calc = StateCalc :: new ( scripts, iimpl. state_abi ) ;
354
+ Ok ( Self :: with ( contract_id, iface, schema, iimpl, transition_type, types, Some ( calc) ) )
357
355
}
358
356
359
357
fn with (
@@ -363,13 +361,15 @@ impl TransitionBuilder {
363
361
iimpl : IfaceImpl ,
364
362
transition_type : TransitionType ,
365
363
types : TypeSystem ,
364
+ calc : Option < StateCalc > ,
366
365
) -> Self {
367
366
Self {
368
367
contract_id,
369
368
builder : OperationBuilder :: with ( iface, schema, iimpl, types) ,
370
369
nonce : u64:: MAX ,
371
370
transition_type,
372
371
inputs : none ! ( ) ,
372
+ calc,
373
373
}
374
374
}
375
375
@@ -403,6 +403,9 @@ impl TransitionBuilder {
403
403
}
404
404
405
405
pub fn add_input ( mut self , opout : Opout , state : State ) -> Result < Self , BuilderError > {
406
+ if let Some ( calc) = & mut self . calc {
407
+ calc. reg_input ( opout. ty , & state) ?;
408
+ }
406
409
self . inputs . insert ( Input :: with ( opout) , state) ?;
407
410
Ok ( self )
408
411
}
@@ -430,39 +433,54 @@ impl TransitionBuilder {
430
433
self . builder . valency_type ( name)
431
434
}
432
435
436
+ #[ inline]
433
437
pub fn valency_name ( & self , type_id : ValencyType ) -> & FieldName {
434
438
self . builder . valency_name ( type_id)
435
439
}
436
440
437
441
pub fn meta_name ( & self , type_id : MetaType ) -> & FieldName { self . builder . meta_name ( type_id) }
438
442
443
+ /// NB: Doesn't process the state with VM
439
444
pub fn add_owned_state_raw (
440
445
mut self ,
441
- name : impl Into < FieldName > ,
446
+ type_id : AssignmentType ,
442
447
seal : impl Into < BuilderSeal < GraphSeal > > ,
443
448
state : State ,
444
449
) -> Result < Self , BuilderError > {
445
- self . builder = self . builder . add_owned_state_raw ( name , seal, state) ?;
450
+ self . builder = self . builder . add_owned_state_raw ( type_id , seal, state) ?;
446
451
Ok ( self )
447
452
}
448
453
449
- pub fn add_owned_state (
454
+ pub fn fulfill_owned_state (
450
455
mut self ,
451
- name : impl Into < FieldName > ,
456
+ type_id : AssignmentType ,
452
457
seal : impl Into < BuilderSeal < GraphSeal > > ,
453
- value : impl StrictSerialize ,
454
- ) -> Result < Self , BuilderError > {
455
- self . builder = self . builder . add_owned_state ( name, seal, value) ?;
456
- Ok ( self )
457
- }
458
-
459
- pub fn add_owned_state_default (
460
- self ,
458
+ state : State ,
459
+ ) -> Result < ( Self , Option < State > ) , BuilderError > {
460
+ let calc = self
461
+ . calc
462
+ . as_mut ( )
463
+ . expect ( "you must not call fulfill_owned_state for the blank transition builder" ) ;
464
+ let state = calc. calc_output ( type_id, & state) ?;
465
+ self . builder = self
466
+ . builder
467
+ . add_owned_state_raw ( type_id, seal, state. sufficient ) ?;
468
+ Ok ( ( self , state. insufficient ) )
469
+ }
470
+
471
+ pub fn add_owned_state_change (
472
+ mut self ,
473
+ type_id : AssignmentType ,
461
474
seal : impl Into < BuilderSeal < GraphSeal > > ,
462
- value : impl StrictSerialize ,
463
475
) -> Result < Self , BuilderError > {
464
- let assignment_name = self . default_assignment ( ) ?. clone ( ) ;
465
- self . add_owned_state ( assignment_name, seal. into ( ) , value)
476
+ let calc = self
477
+ . calc
478
+ . as_mut ( )
479
+ . expect ( "you must not call add_owned_state_change for the blank transition builder" ) ;
480
+ if let Some ( state) = calc. calc_change ( type_id) ? {
481
+ self . builder = self . builder . add_owned_state_raw ( type_id, seal, state) ?;
482
+ }
483
+ Ok ( self )
466
484
}
467
485
468
486
pub fn has_inputs ( & self ) -> bool { !self . inputs . is_empty ( ) }
@@ -514,7 +532,6 @@ impl<Seal: ExposedSeal> OperationBuilder<Seal> {
514
532
global : none ! ( ) ,
515
533
assignments : none ! ( ) ,
516
534
meta : none ! ( ) ,
517
-
518
535
types,
519
536
}
520
537
}
@@ -551,14 +568,6 @@ impl<Seal: ExposedSeal> OperationBuilder<Seal> {
551
568
self . iimpl . valency_name ( ty) . expect ( "internal inconsistency" )
552
569
}
553
570
554
- #[ inline]
555
- fn state_schema ( & self , type_id : AssignmentType ) -> & OwnedStateSchema {
556
- self . schema
557
- . owned_types
558
- . get ( & type_id)
559
- . expect ( "schema should match interface: must be checked by the constructor" )
560
- }
561
-
562
571
#[ inline]
563
572
fn meta_schema ( & self , type_id : MetaType ) -> & SemId {
564
573
self . schema
@@ -615,16 +624,10 @@ impl<Seal: ExposedSeal> OperationBuilder<Seal> {
615
624
616
625
fn add_owned_state_raw (
617
626
mut self ,
618
- name : impl Into < FieldName > ,
627
+ type_id : AssignmentType ,
619
628
seal : impl Into < BuilderSeal < Seal > > ,
620
629
state : State ,
621
630
) -> Result < Self , BuilderError > {
622
- let name = name. into ( ) ;
623
-
624
- let type_id = self
625
- . assignments_type ( & name)
626
- . ok_or ( BuilderError :: AssignmentNotFound ( name) ) ?;
627
-
628
631
let assignment = seal. into ( ) . assignment ( state) ;
629
632
630
633
match self . assignments . entry ( type_id) ? {
@@ -644,7 +647,13 @@ impl<Seal: ExposedSeal> OperationBuilder<Seal> {
644
647
seal : impl Into < BuilderSeal < Seal > > ,
645
648
value : impl StrictSerialize ,
646
649
) -> Result < Self , BuilderError > {
647
- self . add_owned_state_raw ( name, seal, State :: new ( value) )
650
+ let name = name. into ( ) ;
651
+
652
+ let type_id = self
653
+ . assignments_type ( & name)
654
+ . ok_or ( BuilderError :: AssignmentNotFound ( name) ) ?;
655
+
656
+ self . add_owned_state_raw ( type_id, seal, State :: new ( value) )
648
657
}
649
658
650
659
fn complete ( self ) -> ( Schema , Iface , IfaceImpl , GlobalState , Assignments < Seal > , TypeSystem ) {
0 commit comments