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

Finalize ADR-028 #8398

Merged
merged 32 commits into from
Feb 4, 2021
Merged

Finalize ADR-028 #8398

merged 32 commits into from
Feb 4, 2021

Conversation

robert-zaremba
Copy link
Collaborator

Description

closes: #8397


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


### Requirements

+ Support currently used tools - we don't want to break an ecosystem, or add a long adaptation period.
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this be more explicit? What tools in particular, is the goal here to just be keeping secp key formats as is?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Mainly wallets or services which already relay on the current addresse. More details about this is at #8041 I will link it directly in the ADR.

const A_LEN = 32

func BaseAddress(typ string, pubkey []byte) []byte {
return hash(hash(typ) + pubkey)[:A_LEN]
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not do a personalization string if the underlying hash supports it?

Its also worth noting, that for efficiency, hash(typ) should ideally have length block size OR size(hash(type) + pubkey) < 1 block size

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'm not sure I follow you:

  • What do you mean with _ personalization string_?
  • The returned bytes are capped at A_LEN. hash is defined in the section above. I specifically, didn't want to name it here -- in case we will edit it, we only need to change one place.
  • With block size - you mane a blockchain block size? That's totally different scale.

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
docs/architecture/adr-028-public-key-addresses.md Outdated Show resolved Hide resolved
Copy link
Contributor

@clevinson clevinson left a comment

Choose a reason for hiding this comment

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

Thanks for the updates @robert-zaremba! Can you make these last few updates and then mark re-request review so we can get this merged in ?

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

```proto
package cosmos.crypto.sr25519;
### Composed Account Addresses
Copy link
Member

Choose a reason for hiding this comment

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

Please remove this section and consider reverting to the previous multisig format. As we discussed live generalizing multisig keys to composed addresses is a nice idea but doesn't work because there are too many specifics like threshold which isn't here.

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 reverted and merged the Multisig Addresses section here. My motivation here is to show a generic function to compose pubkeys, and use multisig as an example. I think it's better to make this abstraction, rather than re-implement it in other account types.

Copy link
Member

Choose a reason for hiding this comment

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

Well even so, I don't think this is actually correct, the concatenated addresses each need to be length prefixed because they can be variable length. But otherwise, maybe it works...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's why we use .Address() function for all sub addresses - it will have the required logic. Compose is a one way function, there is nothing to decode.

Copy link
Member

Choose a reason for hiding this comment

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

Maybe my comment wasn't clear but we need to length prefix before concatenation because otherwise the boundary between addresses isn't clear

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Let me give more context. The motivation to have this section is to:

  1. Show that we are not in the dead end and we have positive consequences of address composability (as outlined in the consequences section)
  2. we have algorithm for that
  3. new multisig is just an example, but the main topic is composition.

Copy link
Member

Choose a reason for hiding this comment

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

I think that's okay, I'm not there's another use case but it looks okay.

This is what I was trying to say: https://github.com/cosmos/cosmos-sdk/pull/8398/files#r566337924

func Composed(typ string, subaccounts []Addressable) []byte {
addresses = map(subaccounts, \a -> a.Address())
addresses = sort(addresses)
return address.Hash(typ, addresses[0] + ... + addresses[n])
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return address.Hash(typ, addresses[0] + ... + addresses[n])
return address.Hash(typ, LengthPrefixAddress(addresses[0]) + ... + LengthPrefixAddress(addresses[n]))

Copy link
Member

Choose a reason for hiding this comment

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

Without length prefixing each address here you don't know the boundary. The addresses could be 20 or 32 bytes or some other number of users choose. So you can't successfully compose without that. Otherwise, there could be some weird collisions however unlikely.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Composed is a one-way function - once hashed, we can't go back. We don't need to know boundaries - finding a collision with length prefixing is as hard as finding a collision without them. We can map LengthPrefixAddress to all sub addresses, but I don't see any justification for that. Meaning it obfuscates the code but it doesn't enhance the security.

Copy link
Collaborator Author

@robert-zaremba robert-zaremba Jan 28, 2021

Choose a reason for hiding this comment

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

Practically speaking, the only way we could get a collision is when we have two sequences of addresses which concatenate to the same string:

as, bs [][]byte <- list of addresses

So, the question is not about the hash collision, but key construction. Specifically: is it harder to find 2 different list of addresses (as != bs) for having a match in A or in B?

A:  as[0]+as[1]+...+as[n] =? bs[0]+bs[1]+...+bs[m]
B:  lenpref(as[0])+lenpref(as[1])+...+lenpref(as[n]) =? lenpref(bs[0])+lenpref(bs[1])+...+lenpref(bs[m])

so, lets think...

Copy link
Collaborator Author

@robert-zaremba robert-zaremba Jan 28, 2021

Choose a reason for hiding this comment

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

Each problem can be solved by a construction: we map and concatenate. Then for constructing bs we try to slice the concatenate sequence just before some 1 bits.
Specifically, for problem B, here is an example of conflicting addresses in binary form:

as = {0101, 1000, 1}
bs = {00, 101000 11}
map(lenpref, as) = {10 0  100,  10 1000, 11  }
map(lenpref, as) = {10 0, 100   10 1000  11 }

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 was thinking more about it. Since the length prefix is always 1 byte, then we can't construct conflicting address sequences unless the individual addresses are the same - so the lenpref in this case will work.
Other solution I had in mind was to hash each subaddress before concatenation - this way all parts have exactly same length.

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, the collision risk may be small but length-prefixing is cheap and ensures zero collisions in the pre-image.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@aaronc , yes, in OP, when you wrote about collision I thought you are writing about hash collision ;) In the (updated) text I use conflict instead of collision.

Copy link
Contributor

@alessio alessio left a comment

Choose a reason for hiding this comment

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

Nihil obstat from me

@robert-zaremba robert-zaremba requested a review from aaronc January 31, 2021 23:36
Copy link
Member

@aaronc aaronc left a comment

Choose a reason for hiding this comment

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

ACK 🎉

Left a bunch of minor suggestions, mostly grammar related

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
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
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
@robert-zaremba
Copy link
Collaborator Author

I'm changing the status back to Proposed
This week we added more considerations for module derived accounts. We left few notes in the ADR to continue discussion about this.

The basic part: address generation of simple accounts (key paris) and modules we consider stable and validated.

@robert-zaremba robert-zaremba added the A:automerge Automatically merge PR once all prerequisites pass. label Feb 3, 2021
@robert-zaremba robert-zaremba merged commit 931af43 into master Feb 4, 2021
@robert-zaremba robert-zaremba deleted the robert/adr-28 branch February 4, 2021 03:08
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.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Finalize ADR-28
7 participants