github.com/koko1123/flow-go-1@v0.29.6/fvm/environment/uuids.go (about) 1 package environment 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 7 "github.com/koko1123/flow-go-1/fvm/state" 8 "github.com/koko1123/flow-go-1/fvm/tracing" 9 "github.com/koko1123/flow-go-1/module/trace" 10 "github.com/koko1123/flow-go-1/utils/slices" 11 ) 12 13 type UUIDGenerator interface { 14 GenerateUUID() (uint64, error) 15 } 16 17 type ParseRestrictedUUIDGenerator struct { 18 txnState *state.TransactionState 19 impl UUIDGenerator 20 } 21 22 func NewParseRestrictedUUIDGenerator( 23 txnState *state.TransactionState, 24 impl UUIDGenerator, 25 ) UUIDGenerator { 26 return ParseRestrictedUUIDGenerator{ 27 txnState: txnState, 28 impl: impl, 29 } 30 } 31 32 func (generator ParseRestrictedUUIDGenerator) GenerateUUID() (uint64, error) { 33 return parseRestrict1Ret( 34 generator.txnState, 35 trace.FVMEnvGenerateUUID, 36 generator.impl.GenerateUUID) 37 } 38 39 type uUIDGenerator struct { 40 tracer tracing.TracerSpan 41 meter Meter 42 43 txnState *state.TransactionState 44 } 45 46 func NewUUIDGenerator( 47 tracer tracing.TracerSpan, 48 meter Meter, 49 txnState *state.TransactionState, 50 ) *uUIDGenerator { 51 return &uUIDGenerator{ 52 tracer: tracer, 53 meter: meter, 54 txnState: txnState, 55 } 56 } 57 58 // GetUUID reads uint64 byte value for uuid from the state 59 func (generator *uUIDGenerator) getUUID() (uint64, error) { 60 stateBytes, err := generator.txnState.Get( 61 "", 62 state.UUIDKey, 63 generator.txnState.EnforceLimits()) 64 if err != nil { 65 return 0, fmt.Errorf("cannot get uuid byte from state: %w", err) 66 } 67 bytes := slices.EnsureByteSliceSize(stateBytes, 8) 68 69 return binary.BigEndian.Uint64(bytes), nil 70 } 71 72 // SetUUID sets a new uint64 byte value 73 func (generator *uUIDGenerator) setUUID(uuid uint64) error { 74 bytes := make([]byte, 8) 75 binary.BigEndian.PutUint64(bytes, uuid) 76 err := generator.txnState.Set( 77 "", 78 state.UUIDKey, 79 bytes, 80 generator.txnState.EnforceLimits()) 81 if err != nil { 82 return fmt.Errorf("cannot set uuid byte to state: %w", err) 83 } 84 return nil 85 } 86 87 // GenerateUUID generates a new uuid and persist the data changes into state 88 func (generator *uUIDGenerator) GenerateUUID() (uint64, error) { 89 defer generator.tracer.StartExtensiveTracingChildSpan( 90 trace.FVMEnvGenerateUUID).End() 91 92 err := generator.meter.MeterComputation( 93 ComputationKindGenerateUUID, 94 1) 95 if err != nil { 96 return 0, fmt.Errorf("generate uuid failed: %w", err) 97 } 98 99 uuid, err := generator.getUUID() 100 if err != nil { 101 return 0, fmt.Errorf("cannot generate UUID: %w", err) 102 } 103 104 err = generator.setUUID(uuid + 1) 105 if err != nil { 106 return 0, fmt.Errorf("cannot generate UUID: %w", err) 107 } 108 return uuid, nil 109 }