ADR-28 derive address functions (#9088)
* update Derive functions * update adr-028 * changelog update * Apply suggestions from code review Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com> * review updates * remove DeriveMulti and rollback some changes in CHANGELOG * add noop error check Co-authored-by: Marie Gauthier <marie.gauthier63@gmail.com>
This commit is contained in:
co-authored by
Marie Gauthier
parent
261c7ebd89
commit
e43edc4749
@@ -135,7 +135,7 @@ type Addressable interface {
|
||||
Address() []byte
|
||||
}
|
||||
|
||||
func NewComposed(typ string, subaccounts []Addressable) []byte {
|
||||
func Composed(typ string, subaccounts []Addressable) []byte {
|
||||
addresses = map(subaccounts, \a -> LengthPrefix(a.Address()))
|
||||
addresses = sort(addresses)
|
||||
return address.Hash(typ, addresses[0] + ... + addresses[n])
|
||||
@@ -175,7 +175,7 @@ func (multisig PubKey) Address() {
|
||||
prefix := fmt.Sprintf("%s/%d", proto.MessageName(multisig), multisig.Threshold)
|
||||
|
||||
// use the Composed function defined above
|
||||
return address.NewComposed(prefix, keys)
|
||||
return address.Composed(prefix, keys)
|
||||
}
|
||||
```
|
||||
|
||||
@@ -185,14 +185,14 @@ NOTE: this section is not finalize and it's in active discussion.
|
||||
|
||||
In Basic Address section we defined a module account address as:
|
||||
|
||||
```
|
||||
```go
|
||||
address.Hash("module", moduleName)
|
||||
```
|
||||
|
||||
We use `"module"` as a schema type for all module derived addresses. Module accounts can have sub accounts. The derivation process has a defined order: module name, submodule key, subsubmodule key.
|
||||
Module account addresses are heavily used in the SDK so it makes sense to optimize the derivation process: instead of using of using `LengthPrefix` for the module name, we use a null byte (`'\x00'`) as a separator. This works, because null byte is not a part of a valid module name.
|
||||
|
||||
```
|
||||
```go
|
||||
func Module(moduleName string, key []byte) []byte{
|
||||
return Hash("module", []byte(moduleName) + 0 + key)
|
||||
}
|
||||
@@ -208,24 +208,24 @@ If we want to create an address for a module account depending on more than one
|
||||
btcAtomAMM := address.Module("amm", btc.Addrress() + atom.Address()})
|
||||
```
|
||||
|
||||
We can continue the derivation process and can create an address for a submodule account.
|
||||
#### Derived Addresses
|
||||
|
||||
```
|
||||
func Submodule(address []byte, derivationKey []byte) {
|
||||
return Hash("module", address + derivationKey)
|
||||
We must be able to cryptographically derive one address from another one. The derivation process must guarantee hash properties, hence we use the already defined `Hash` function:
|
||||
|
||||
```go
|
||||
func Derive(address []byte, derivationKey []byte) []byte {
|
||||
return Hash(addres, derivationKey)
|
||||
}
|
||||
```
|
||||
|
||||
NOTE: if `address` is not a hash based address (with `LEN` length) then we should use `LengthPrefix`. An alternative would be to use one `Module` function, which takes a slice of keys and mapped with `LengthPrefix`. For final version we need to validate what's the most common use.
|
||||
|
||||
Note: `Module` is a special case of the more general _derived_ address, where we set the `"module"` string for the _from address_.
|
||||
|
||||
**Example** For a cosmwasm smart-contract address we could use the following construction:
|
||||
```
|
||||
smartContractAddr := Submodule(Module("cosmwasm", smartContractsNamespace), smartContractKey)
|
||||
smartContractAddr := Derived(Module("cosmwasm", smartContractsNamespace), []{smartContractKey})
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Schema Types
|
||||
|
||||
A `typ` parameter used in `Hash` function SHOULD be unique for each account type.
|
||||
|
||||
Reference in New Issue
Block a user