forked from cosmos/cosmos-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adr-028 address generation (cosmos#8415)
* Optimize secp256k1 hashing * Add ADR-028 related functions * Update ed25519 * fix errors/handle * fix build * fix build * Add tests and update function names * wip * Use LengthPrefix for composed addresses * add tests for NewComposed * add module hash function * fix append * rollback ed25519 ADR-28 update * rollback ed25519 ADR-28 test * Adding Module tests and convert tests to test suite * convert store_key_test.go to test suite * rollback test check comment * Rename assert.Panic and add comment * add note to ed25519 about SDK support with regards to ADR-28 * Update ed25519 TestAddress * Adding Deprecated notes for ed25519.PrivKey * Update crypto/keys/ed25519/ed25519.go Co-authored-by: Marie Gauthier <[email protected]> * Update types/address/hash_test.go Co-authored-by: Marie Gauthier <[email protected]> * solve linter issues * linter: remove gocritic Co-authored-by: Marie Gauthier <[email protected]>
- Loading branch information
1 parent
b4690d8
commit adbf5a7
Showing
16 changed files
with
239 additions
and
37 deletions.
There are no files selected for viewing
This file contains 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 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 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 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 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
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains 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 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 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 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,7 @@ | ||
# Account | ||
|
||
This package defines Cosmos SDK address related functions. | ||
|
||
## References | ||
|
||
+ [ADR-028](../../docs/architecture/adr-028-public-key-addresses.md) |
This file contains 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,74 @@ | ||
package address | ||
|
||
import ( | ||
"bytes" | ||
"crypto/sha256" | ||
"fmt" | ||
"reflect" | ||
"sort" | ||
"unsafe" | ||
|
||
"github.com/cosmos/cosmos-sdk/types/errors" | ||
) | ||
|
||
// Len is the length of base addresses | ||
const Len = sha256.Size | ||
|
||
type Addressable interface { | ||
Address() []byte | ||
} | ||
|
||
// Hash creates a new address from address type and key | ||
func Hash(typ string, key []byte) []byte { | ||
hasher := sha256.New() | ||
hasher.Write(unsafeStrToByteArray(typ)) | ||
th := hasher.Sum(nil) | ||
|
||
hasher.Reset() | ||
_, err := hasher.Write(th) | ||
// the error always nil, it's here only to satisfy the io.Writer interface | ||
errors.AssertNil(err) | ||
_, err = hasher.Write(key) | ||
errors.AssertNil(err) | ||
return hasher.Sum(nil) | ||
} | ||
|
||
// NewComposed creates a new address based on sub addresses. | ||
func NewComposed(typ string, subAddresses []Addressable) ([]byte, error) { | ||
as := make([][]byte, len(subAddresses)) | ||
totalLen := 0 | ||
var err error | ||
for i := range subAddresses { | ||
a := subAddresses[i].Address() | ||
as[i], err = LengthPrefix(a) | ||
if err != nil { | ||
return nil, fmt.Errorf("not compatible sub-adddress=%v at index=%d [%w]", a, i, err) | ||
} | ||
totalLen += len(as[i]) | ||
} | ||
|
||
sort.Slice(as, func(i, j int) bool { return bytes.Compare(as[i], as[j]) <= 0 }) | ||
key := make([]byte, totalLen) | ||
offset := 0 | ||
for i := range as { | ||
copy(key[offset:], as[i]) | ||
offset += len(as[i]) | ||
} | ||
return Hash(typ, key), nil | ||
} | ||
|
||
// Module is a specialized version of a composed address for modules. Each module account | ||
// is constructed from a module name and module account key. | ||
func Module(moduleName string, key []byte) []byte { | ||
mKey := append([]byte(moduleName), 0) | ||
return Hash("module", append(mKey, key...)) | ||
} | ||
|
||
// unsafeStrToByteArray uses unsafe to convert string into byte array. Returned array | ||
// cannot be altered after this functions is called | ||
func unsafeStrToByteArray(s string) []byte { | ||
sh := *(*reflect.SliceHeader)(unsafe.Pointer(&s)) | ||
sh.Cap = sh.Len | ||
bs := *(*[]byte)(unsafe.Pointer(&sh)) | ||
return bs | ||
} |
This file contains 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,90 @@ | ||
package address | ||
|
||
import ( | ||
"crypto/sha256" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/suite" | ||
) | ||
|
||
func TestAddressSuite(t *testing.T) { | ||
suite.Run(t, new(AddressSuite)) | ||
} | ||
|
||
type AddressSuite struct{ suite.Suite } | ||
|
||
func (suite *AddressSuite) TestHash() { | ||
assert := suite.Assert() | ||
typ := "1" | ||
key := []byte{1} | ||
part1 := sha256.Sum256([]byte(typ)) | ||
expected := sha256.Sum256(append(part1[:], key...)) | ||
received := Hash(typ, key) | ||
assert.Equal(expected[:], received, "must create a correct address") | ||
|
||
received = Hash("other", key) | ||
assert.NotEqual(expected[:], received, "must create a correct address") | ||
assert.Len(received, Len, "must have correct length") | ||
} | ||
|
||
func (suite *AddressSuite) TestComposed() { | ||
assert := suite.Assert() | ||
a1 := addrMock{[]byte{11, 12}} | ||
a2 := addrMock{[]byte{21, 22}} | ||
|
||
typ := "multisig" | ||
ac, err := NewComposed(typ, []Addressable{a1, a2}) | ||
assert.NoError(err) | ||
assert.Len(ac, Len) | ||
|
||
// check if optimizations work | ||
checkingKey := append([]byte{}, a1.AddressWithLen(suite.T())...) | ||
checkingKey = append(checkingKey, a2.AddressWithLen(suite.T())...) | ||
ac2 := Hash(typ, checkingKey) | ||
assert.Equal(ac, ac2, "NewComposed works correctly") | ||
|
||
// changing order of addresses shouldn't impact a composed address | ||
ac2, err = NewComposed(typ, []Addressable{a2, a1}) | ||
assert.NoError(err) | ||
assert.Len(ac2, Len) | ||
assert.Equal(ac, ac2, "NewComposed is not sensitive for order") | ||
|
||
// changing a type should change composed address | ||
ac2, err = NewComposed(typ+"other", []Addressable{a2, a1}) | ||
assert.NoError(err) | ||
assert.NotEqual(ac, ac2, "NewComposed must be sensitive to type") | ||
|
||
// changing order of addresses shouldn't impact a composed address | ||
ac2, err = NewComposed(typ, []Addressable{a1, addrMock{make([]byte, 300, 300)}}) | ||
assert.Error(err) | ||
assert.Contains(err.Error(), "should be max 255 bytes, got 300") | ||
} | ||
|
||
func (suite *AddressSuite) TestModule() { | ||
assert := suite.Assert() | ||
var modName, key = "myModule", []byte{1, 2} | ||
addr := Module(modName, key) | ||
assert.Len(addr, Len, "must have address length") | ||
|
||
addr2 := Module("myModule2", key) | ||
assert.NotEqual(addr, addr2, "changing module name must change address") | ||
|
||
addr3 := Module(modName, []byte{1, 2, 3}) | ||
assert.NotEqual(addr, addr3, "changing key must change address") | ||
assert.NotEqual(addr2, addr3, "changing key must change address") | ||
} | ||
|
||
type addrMock struct { | ||
Addr []byte | ||
} | ||
|
||
func (a addrMock) Address() []byte { | ||
return a.Addr | ||
} | ||
|
||
func (a addrMock) AddressWithLen(t *testing.T) []byte { | ||
addr, err := LengthPrefix(a.Addr) | ||
assert.NoError(t, err) | ||
return addr | ||
} |
This file contains 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 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,12 @@ | ||
package errors | ||
|
||
import "fmt" | ||
|
||
// AssertNil panics on error | ||
// Should be only used with interface methods, which require return error, but the | ||
// error is always nil | ||
func AssertNil(err error) { | ||
if err != nil { | ||
panic(fmt.Errorf("logic error - this should never happen. %w", err)) | ||
} | ||
} |
Oops, something went wrong.