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  }