diff --git a/core/address.go b/core/address.go index 19494a27a..6c72cb8cc 100644 --- a/core/address.go +++ b/core/address.go @@ -2,6 +2,8 @@ package core import ( "bytes" + "encoding/binary" + "github.com/ElrondNetwork/elrond-go-core/hashing/keccak" ) // SystemAccountAddress is the hard-coded address in which we save global settings on all shards @@ -85,3 +87,46 @@ func IsSmartContractOnMetachain(identifier []byte, rcvAddress []byte) bool { make([]byte, numInitCharactersForOnMetachainSC)) return isOnMetaChainSCAddress } + +// NewAddress creates a new smart contract address from the creators address and nonce +// The address is created by applied keccak256 on the appended value off creator address and nonce +// Prefix mask is applied for first 8 bytes 0, and for bytes 9-10 - VM type +// Suffix mask is applied - last 2 bytes are for the shard ID - mask is applied as suffix mask +func NewAddress(creatorAddress []byte, addressLength int, creatorNonce uint64, vmType []byte) ([]byte, error) { + if len(creatorAddress) != addressLength { + return nil, ErrAddressLengthNotCorrect + } + + if len(vmType) != VMTypeLen { + return nil, ErrVMTypeLengthIsNotCorrect + } + + base := hashFromAddressAndNonce(creatorAddress, creatorNonce) + prefixMask := createPrefixMask(vmType) + suffixMask := createSuffixMask(creatorAddress) + + copy(base[:NumInitCharactersForScAddress], prefixMask) + copy(base[len(base)-ShardIdentiferLen:], suffixMask) + + return base, nil +} + +func hashFromAddressAndNonce(creatorAddress []byte, creatorNonce uint64) []byte { + buffNonce := make([]byte, 8) + binary.LittleEndian.PutUint64(buffNonce, creatorNonce) + adrAndNonce := append(creatorAddress, buffNonce...) + scAddress := keccak.NewKeccak().Compute(string(adrAndNonce)) + + return scAddress +} + +func createPrefixMask(vmType []byte) []byte { + prefixMask := make([]byte, NumInitCharactersForScAddress-VMTypeLen) + prefixMask = append(prefixMask, vmType...) + + return prefixMask +} + +func createSuffixMask(creatorAddress []byte) []byte { + return creatorAddress[len(creatorAddress)-2:] +} diff --git a/core/errors.go b/core/errors.go index b11bc7f1e..4473c5dea 100644 --- a/core/errors.go +++ b/core/errors.go @@ -106,3 +106,9 @@ var ErrNilLogger = errors.New("nil logger") // ErrNilGoRoutineProcessor signals that a nil go routine processor has been provided var ErrNilGoRoutineProcessor = errors.New("nil go routine processor") + +// ErrAddressLengthNotCorrect signals that an account does not have the correct address +var ErrAddressLengthNotCorrect = errors.New("address length is not correct") + +// ErrVMTypeLengthIsNotCorrect signals that the vm type length is not correct +var ErrVMTypeLengthIsNotCorrect = errors.New("vm type length is not correct")