Skip to content
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

ADR-28 derive address functions #9088

Merged
merged 9 commits into from
Apr 15, 2021
Merged

ADR-28 derive address functions #9088

merged 9 commits into from
Apr 15, 2021

Conversation

robert-zaremba
Copy link
Collaborator

@robert-zaremba robert-zaremba commented Apr 9, 2021

Description

In ADR-28 we left over the Derive function while waiting for first use-cases and usage. Now we are need it for group module.

closes: #9033


Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.

  • Targeted PR against correct branch (see CONTRIBUTING.md)
  • Linked to Github issue with discussion and accepted design OR link to spec that describes this work.
  • Code follows the module structure standards.
  • Wrote unit and integration tests
  • Updated relevant documentation (docs/) or specification (x/<module>/spec/)
  • Added relevant godoc comments.
  • Added a relevant changelog entry to the Unreleased section in CHANGELOG.md
  • Re-reviewed Files changed in the Github PR explorer
  • Review Codecov Report in the comment section below once CI passes

@robert-zaremba robert-zaremba added the T: ADR An issue or PR relating to an architectural decision record label Apr 9, 2021
@robert-zaremba robert-zaremba changed the title Robert/address derive ADR-28 address derive functions Apr 9, 2021
@robert-zaremba robert-zaremba changed the title ADR-28 address derive functions ADR-28 derive address functions Apr 9, 2021
```go
func DeriveMulti(address []byte, derivationKeys [][]byte) {
keys = map(derivationKeys, \k -> LengthPrefix(k))
return Hash(LengthPrefix(address), keys[0] + ... + keys[n])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit confusing for me that Derive doesn't length-prefix derivationKey, and DeriveMulti length-prefixes.

I understand Derive doesn't need legnth-prefixing. But isn't it just simpler to always use the same algorithm (i.e. always lenght-prefix), so that Derive == DeriveMulti with 1 derivationKey?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, we use length prefixing only if we want to glue a sequence of keys. So, for Derive it's unnecessary operation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, for Derive it's unnecessary operation.

Yes, but does it create more confusion? We could just:

func Derive(address []byte, derivationKey []byte) []byte {
    return DeriveMulti(address, []byte{derivationKey})
}

so that we have 1 algorithm only.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the confusion will be there anyway: DeriveMulti doesn't decompose into multiple Derive calls (even with LengthPrfixing) - what's in the function comment:

// NOTE: DeriveMulti(addr, [k1, k2]) != Derive(Derive(addr, k1), k2)
//                                   != Derive(Derive(addr, k2), k1)

The motivation here was to use a composed derivation path, Normally we would put slashes into the segments. But here, the key can be anything, so we can't have any special separator.

So to summarize, we have 3 options:

  1. leave as is
  2. remove DeriveMulti, and not adding it later in the form described above.
  3. use @AmauryM suggestion to use

Maybe we don't need DeriveMuli - it seams that we will always have the parent key and will never derive into subusub-account without having a sub-account. What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// NOTE: DeriveMulti(addr, [k1, k2]) != Derive(Derive(addr, k1), k2)
// != Derive(Derive(addr, k2), k1)

Another option:

  1. DeriveMulti is composition of Derive
func DeriveMulti(address []byte, derivationKeys [][]byte) {
  result := address
  for _, derivKey := range derivationKeys {
    result = Derive(result, derivKey)
  }
  return result
}

The 1st line of your NOTE is then an equality (less confusion), and we never use length-prefixing (also less confusion). The 2nd line stays an inequality, but in general compositions are never commutative.

Maybe we don't need DeriveMuli - it seams that we will always have the parent key and will never derive into subusub-account without having a sub-account. What do you think?

True, that also makes sense. Overall I'm actually in favor of Option 2: remove DeriveMulti for now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's why I was more thinking about the Option 2. Again, the motivation for DeriveMulti was not to use composition.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean - the motivation was to have a sequence of parameters, which don't compose, but use the whole sequence as a single parameter (as we have in the hardware wallets now).

CHANGELOG.md Outdated Show resolved Hide resolved
docs/architecture/adr-028-public-key-addresses.md Outdated Show resolved Hide resolved
docs/architecture/adr-028-public-key-addresses.md Outdated Show resolved Hide resolved
docs/architecture/adr-028-public-key-addresses.md Outdated Show resolved Hide resolved
docs/architecture/adr-028-public-key-addresses.md Outdated Show resolved Hide resolved
types/address/hash.go Show resolved Hide resolved
@alessio
Copy link
Contributor

alessio commented Apr 9, 2021

@robert-zaremba mind resolving the conflicts, please?

Copy link
Contributor

@amaury1093 amaury1093 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, thanks

@codecov
Copy link

codecov bot commented Apr 14, 2021

Codecov Report

Merging #9088 (7ee294b) into master (ef69863) will increase coverage by 0.00%.
The diff coverage is 100.00%.

❗ Current head 7ee294b differs from pull request most recent head ba1b14b. Consider uploading reports for the commit ba1b14b to get more accurate results
Impacted file tree graph

@@           Coverage Diff           @@
##           master    #9088   +/-   ##
=======================================
  Coverage   58.79%   58.79%           
=======================================
  Files         583      583           
  Lines       32750    32752    +2     
=======================================
+ Hits        19255    19257    +2     
  Misses      11218    11218           
  Partials     2277     2277           
Impacted Files Coverage Δ
types/address/hash.go 100.00% <100.00%> (ø)
x/bank/types/key.go 80.00% <0.00%> (ø)

@robert-zaremba robert-zaremba added the A:automerge Automatically merge PR once all prerequisites pass. label Apr 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A:automerge Automatically merge PR once all prerequisites pass. T: ADR An issue or PR relating to an architectural decision record
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement Module Derived Addresses
5 participants