github.com/onflow/flow-go@v0.33.17/fvm/evm/handler/addressAllocator.go (about)

     1  package handler
     2  
     3  import (
     4  	"encoding/binary"
     5  
     6  	"github.com/onflow/atree"
     7  
     8  	"github.com/onflow/flow-go/fvm/evm/types"
     9  	"github.com/onflow/flow-go/model/flow"
    10  )
    11  
    12  const ledgerAddressAllocatorKey = "AddressAllocator"
    13  
    14  type AddressAllocator struct {
    15  	led         atree.Ledger
    16  	flexAddress flow.Address
    17  }
    18  
    19  var _ types.AddressAllocator = &AddressAllocator{}
    20  
    21  // NewAddressAllocator constructs a new statefull address allocator
    22  func NewAddressAllocator(led atree.Ledger, flexAddress flow.Address) (*AddressAllocator, error) {
    23  	return &AddressAllocator{
    24  		led:         led,
    25  		flexAddress: flexAddress,
    26  	}, nil
    27  }
    28  
    29  // AllocateAddress allocates an address
    30  func (aa *AddressAllocator) AllocateAddress() (types.Address, error) {
    31  	data, err := aa.led.GetValue(aa.flexAddress[:], []byte(ledgerAddressAllocatorKey))
    32  	if err != nil {
    33  		return types.Address{}, err
    34  	}
    35  	// default value for uuid is 1
    36  	uuid := uint64(1)
    37  	if len(data) > 0 {
    38  		uuid = binary.BigEndian.Uint64(data)
    39  	}
    40  
    41  	target := types.Address{}
    42  	// first 12 bytes would be zero
    43  	// the next 8 bytes would be an increment of the UUID index
    44  	binary.BigEndian.PutUint64(target[12:], uuid)
    45  
    46  	// store new uuid
    47  	newData := make([]byte, 8)
    48  	binary.BigEndian.PutUint64(newData, uuid+1)
    49  	err = aa.led.SetValue(aa.flexAddress[:], []byte(ledgerAddressAllocatorKey), newData)
    50  	if err != nil {
    51  		return types.Address{}, err
    52  	}
    53  
    54  	return target, nil
    55  }