-
Notifications
You must be signed in to change notification settings - Fork 9
En 13550: address generator #153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dragos-rebegea
wants to merge
2
commits into
feat/freeze-account
Choose a base branch
from
EN-13550
base: feat/freeze-account
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| package addressGenerator | ||
|
|
||
| import ( | ||
| "encoding/binary" | ||
|
|
||
| "github.com/ElrondNetwork/elrond-go-core/core" | ||
| "github.com/ElrondNetwork/elrond-go-core/core/check" | ||
| "github.com/ElrondNetwork/elrond-go-core/hashing" | ||
| "github.com/ElrondNetwork/elrond-go-core/hashing/keccak" | ||
| ) | ||
|
|
||
| // addressGenerator is used to generate some addresses based on elrond-go logic | ||
| type addressGenerator struct { | ||
| pubkeyConv core.PubkeyConverter | ||
| hasher hashing.Hasher | ||
| } | ||
|
|
||
| // NewAddressGenerator will create an address generator instance | ||
| func NewAddressGenerator(pubkeyConv core.PubkeyConverter) (*addressGenerator, error) { | ||
| if check.IfNil(pubkeyConv) { | ||
| return nil, core.ErrNilPubkeyConverter | ||
| } | ||
|
|
||
| return &addressGenerator{ | ||
| pubkeyConv: pubkeyConv, | ||
| hasher: keccak.NewKeccak(), | ||
| }, nil | ||
| } | ||
|
|
||
| // NewAddress is a hook which 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 (ag *addressGenerator) NewAddress(creatorAddress []byte, creatorNonce uint64, vmType []byte) ([]byte, error) { | ||
| addressLength := ag.pubkeyConv.Len() | ||
| if len(creatorAddress) != addressLength { | ||
| return nil, ErrAddressLengthNotCorrect | ||
| } | ||
|
|
||
| if len(vmType) != core.VMTypeLen { | ||
| return nil, ErrVMTypeLengthIsNotCorrect | ||
| } | ||
|
|
||
| base := hashFromAddressAndNonce(creatorAddress, creatorNonce) | ||
| prefixMask := createPrefixMask(vmType) | ||
| suffixMask := createSuffixMask(creatorAddress) | ||
|
|
||
| copy(base[:core.NumInitCharactersForScAddress], prefixMask) | ||
| copy(base[len(base)-core.ShardIdentiferLen:], suffixMask) | ||
|
|
||
| return base, nil | ||
| } | ||
|
|
||
| // IsInterfaceNil returns true if there is no value under the interface | ||
| func (ag *addressGenerator) IsInterfaceNil() bool { | ||
| return ag == 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, core.NumInitCharactersForScAddress-core.VMTypeLen) | ||
| prefixMask = append(prefixMask, vmType...) | ||
|
|
||
| return prefixMask | ||
| } | ||
|
|
||
| func createSuffixMask(creatorAddress []byte) []byte { | ||
| return creatorAddress[len(creatorAddress)-2:] | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| package addressGenerator | ||
|
|
||
| import ( | ||
| "bytes" | ||
| "encoding/hex" | ||
| "fmt" | ||
| "testing" | ||
|
|
||
| "github.com/ElrondNetwork/elrond-go-core/core/check" | ||
| "github.com/ElrondNetwork/elrond-go-core/core/mock" | ||
| "github.com/ElrondNetwork/elrond-go-core/core/pubkeyConverter" | ||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| // AddressBytesLen represents the number of bytes of an address | ||
| const AddressBytesLen = 32 | ||
|
|
||
| var AddressPublicKeyConverter, _ = pubkeyConverter.NewBech32PubkeyConverter(AddressBytesLen, &mock.LoggerMock{}) | ||
|
|
||
| func TestBlockChainHookImpl_NewAddressLengthNoGood(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| ag, err := NewAddressGenerator(AddressPublicKeyConverter) | ||
| require.Nil(t, err) | ||
| assert.False(t, check.IfNil(ag)) | ||
|
|
||
| address := []byte("test") | ||
| nonce := uint64(10) | ||
|
|
||
| scAddress, err := ag.NewAddress(address, nonce, []byte("00")) | ||
| assert.Equal(t, ErrAddressLengthNotCorrect, err) | ||
| assert.Nil(t, scAddress) | ||
|
|
||
| address = []byte("1234567890123456789012345678901234567890") | ||
| scAddress, err = ag.NewAddress(address, nonce, []byte("00")) | ||
| assert.Equal(t, ErrAddressLengthNotCorrect, err) | ||
| assert.Nil(t, scAddress) | ||
| } | ||
|
|
||
| func TestBlockChainHookImpl_NewAddressVMTypeTooLong(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| ag, err := NewAddressGenerator(AddressPublicKeyConverter) | ||
| require.Nil(t, err) | ||
|
|
||
| address := []byte("01234567890123456789012345678900") | ||
| nonce := uint64(10) | ||
|
|
||
| vmType := []byte("010") | ||
| scAddress, err := ag.NewAddress(address, nonce, vmType) | ||
| assert.Equal(t, ErrVMTypeLengthIsNotCorrect, err) | ||
| assert.Nil(t, scAddress) | ||
| } | ||
|
|
||
| func TestBlockChainHookImpl_NewAddress(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| ag, err := NewAddressGenerator(AddressPublicKeyConverter) | ||
| require.Nil(t, err) | ||
|
|
||
| address := []byte("01234567890123456789012345678900") | ||
| nonce := uint64(10) | ||
|
|
||
| vmType := []byte("11") | ||
| scAddress1, err := ag.NewAddress(address, nonce, vmType) | ||
| assert.Nil(t, err) | ||
|
|
||
| for i := 0; i < 8; i++ { | ||
| assert.Equal(t, scAddress1[i], uint8(0)) | ||
| } | ||
| assert.True(t, bytes.Equal(vmType, scAddress1[8:10])) | ||
|
|
||
| nonce++ | ||
| scAddress2, err := ag.NewAddress(address, nonce, []byte("00")) | ||
| assert.Nil(t, err) | ||
|
|
||
| assert.False(t, bytes.Equal(scAddress1, scAddress2)) | ||
|
|
||
| fmt.Printf("%s \n%s \n", hex.EncodeToString(scAddress1), hex.EncodeToString(scAddress2)) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| package addressGenerator | ||
|
|
||
| import "errors" | ||
|
|
||
| // 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") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package mock | ||
|
|
||
| // AddressGeneratorStub is a mock implementation of AddressGenerator interface | ||
| type AddressGeneratorStub struct { | ||
| NewAddressCalled func(address []byte, nonce uint64, vmType []byte) ([]byte, error) | ||
| } | ||
|
|
||
| // NewAddress is a mock implementation of NewAddress method | ||
| func (ags *AddressGeneratorStub) NewAddress(address []byte, nonce uint64, vmType []byte) ([]byte, error) { | ||
| if ags.NewAddressCalled != nil { | ||
| return ags.NewAddressCalled(address, nonce, vmType) | ||
| } | ||
| return nil, nil | ||
| } | ||
|
|
||
| // IsInterfaceNil returns true if there is no value under the interface | ||
| func (ags *AddressGeneratorStub) IsInterfaceNil() bool { | ||
| return ags == nil | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating a new keccak hasher instance here instead of using the instance stored in ag.hasher field is inefficient and inconsistent.