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 001: coin cross-chain transfer source tracing #6662

Merged
merged 68 commits into from
Aug 3, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
0833c55
adr: coin cross-chain transfer source tracing
fedekunze Jul 9, 2020
6bca8df
update pros and cons
fedekunze Jul 9, 2020
13cf126
update spec README
fedekunze Jul 9, 2020
ca1de7e
Merge branch 'master' into adr-coin-source-tracing
fedekunze Jul 15, 2020
3a9dc3e
Update docs/architecture/adr-001-coin-source-tracing.md
fedekunze Jul 21, 2020
5532428
Apply suggestions from code review
fedekunze Jul 21, 2020
82a30db
Update docs/architecture/adr-001-coin-source-tracing.md
fedekunze Jul 21, 2020
5abb1ed
Merge branch 'master' of github.com:cosmos/cosmos-sdk into adr-coin-s…
fedekunze Jul 22, 2020
a4fdab9
Merge branch 'master' of github.com:cosmos/cosmos-sdk into adr-coin-s…
fedekunze Jul 22, 2020
5ba6b58
address comments from review
fedekunze Jul 22, 2020
2f69f4d
update ADR with Send/Recv logic
fedekunze Jul 22, 2020
0dab556
Merge branch 'master' into adr-coin-source-tracing
fedekunze Jul 22, 2020
7ebf21b
final touches
fedekunze Jul 22, 2020
56d2b11
Merge branch 'adr-coin-source-tracing' of github.com:cosmos/cosmos-sd…
fedekunze Jul 22, 2020
3ff4bb9
Merge branch 'master' of github.com:cosmos/cosmos-sdk into adr-coin-s…
fedekunze Jul 22, 2020
fbaf655
Apply suggestions from code review
fedekunze Jul 22, 2020
1954510
address comments from review
fedekunze Jul 22, 2020
95199d5
address @aaronc review comments
fedekunze Jul 22, 2020
38d99eb
Merge branch 'master' into adr-coin-source-tracing
cwgoes Jul 23, 2020
d63f0c9
Apply suggestions from code review
fedekunze Jul 23, 2020
628ec72
use SplitN
fedekunze Jul 23, 2020
33ba62e
custom denom validation reference
fedekunze Jul 23, 2020
80d76b0
Merge branch 'master' into adr-coin-source-tracing
alexanderbez Jul 23, 2020
8591fc3
Merge branch 'master' of github.com:cosmos/cosmos-sdk into adr-coin-s…
fedekunze Jul 28, 2020
1e8f02f
address some comments from review
fedekunze Jul 28, 2020
ae34c2c
more updates based on Colin's review
fedekunze Jul 28, 2020
4da7e85
final draft with changes to relay.go
fedekunze Jul 28, 2020
18bc6ec
Merge branch 'master' into adr-coin-source-tracing
fedekunze Jul 28, 2020
1560d6d
undo proto changes
fedekunze Jul 28, 2020
ed677ec
Merge branch 'adr-coin-source-tracing' of github.com:cosmos/cosmos-sd…
fedekunze Jul 28, 2020
8e5c044
Merge branch 'master' into adr-coin-source-tracing
fedekunze Jul 28, 2020
6d3b25f
address @aaronc review comments
fedekunze Jul 28, 2020
152b2e1
Merge branch 'adr-coin-source-tracing' of github.com:cosmos/cosmos-sd…
fedekunze Jul 28, 2020
e9ccb3c
why do I keep updating the proto files?
fedekunze Jul 28, 2020
295d93c
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Jul 29, 2020
f35a843
address @AdityaSripal comments
fedekunze Jul 29, 2020
54ee703
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Jul 29, 2020
e66e0e3
address more comments
fedekunze Jul 30, 2020
dd564e8
Merge branch 'adr-coin-source-tracing' of github.com:cosmos/cosmos-sd…
fedekunze Jul 30, 2020
a7f99d0
typos
fedekunze Jul 30, 2020
52b621b
Merge branch 'master' into adr-coin-source-tracing
fedekunze Jul 30, 2020
ae3b4b3
final ammendments
fedekunze Jul 30, 2020
b73908d
Merge branch 'adr-coin-source-tracing' of github.com:cosmos/cosmos-sd…
fedekunze Jul 30, 2020
6fd5c19
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Jul 30, 2020
810d517
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Jul 30, 2020
a18409e
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Jul 30, 2020
cdc1d66
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Jul 30, 2020
88994bb
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Jul 30, 2020
d3de242
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Jul 30, 2020
f886641
minor fix
fedekunze Jul 30, 2020
e8d754f
Merge branch 'adr-coin-source-tracing' of github.com:cosmos/cosmos-sd…
fedekunze Jul 30, 2020
c205a8d
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Jul 30, 2020
877d67f
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Jul 30, 2020
cadeacf
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Jul 31, 2020
3a69288
Merge branch 'master' of github.com:cosmos/cosmos-sdk into adr-coin-s…
fedekunze Jul 31, 2020
a71be5c
Merge branch 'adr-coin-source-tracing' of github.com:cosmos/cosmos-sd…
fedekunze Jul 31, 2020
7b882c4
address more comments
fedekunze Jul 31, 2020
226eb92
update example
fedekunze Jul 31, 2020
c0cab23
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Jul 31, 2020
ea3655c
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Jul 31, 2020
9a9b144
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Aug 1, 2020
75a3eff
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Aug 2, 2020
59363c1
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Aug 2, 2020
18e86c1
Update docs/architecture/adr-001-coin-source-tracing.md
fedekunze Aug 3, 2020
2dcfff2
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Aug 3, 2020
07b9ec0
Merge branch 'master' into adr-coin-source-tracing
mergify[bot] Aug 3, 2020
cb4907f
address more comments
fedekunze Aug 3, 2020
c01d0da
update prefix example
fedekunze Aug 3, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/architecture/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Please add a entry below in your Pull Request for an ADR.

## ADR Table of Contents

- [ADR 001: Coin Source Tracing](./adr-001-coin-source-tracing.md)
- [ADR 002: SDK Documentation Structure](./adr-002-docs-structure.md)
- [ADR 003: Dynamic Capability Store](./adr-003-dynamic-capability-store.md)
- [ADR 004: Split Denomination Keys](./adr-004-split-denomination-keys.md)
Expand All @@ -50,3 +51,4 @@ Please add a entry below in your Pull Request for an ADR.
- [ADR 022: Custom baseapp panic handling](./adr-022-custom-panic-handling.md)
- [ADR 023: Protocol Buffer Naming and Versioning](./adr-023-protobuf-naming.md)
- [ADR 024: Coin Metadata](./adr-024-coin-metadata.md)
- [ADR 025: IBC Passive Channels](./adr-025-ibc-passive-channels.md)
178 changes: 178 additions & 0 deletions docs/architecture/adr-001-coin-source-tracing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# ADR 001: Coin Source Tracing

## Changelog

- 2020-07-09: Initial Draft

## Status

Proposed

## Context

The specification for IBC cross-chain fungible token transfers
([ICS20](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer)), needs to
be aware of the origin any token denomination in order to relay a `Packet` which contains the sender
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
and recipient addressed in the
[`FungibleTokenPacketData`](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#data-structures).

The Packet relay works as follows (per
[specification](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer#packet-relay)):

> - When acting as the **source** zone, the bridge module escrows an existing local asset
> denomination on the sending chain and mints vouchers on the receiving chain.
> - When acting as the **sink** zone, the bridge module burns local vouchers on the sending chains
> and unescrows the local asset denomination on the receiving chain.

In this context, when the sender of a cross-chain transfer is **not** the source where the tokens
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
were originated, the protocol prefixes the denomination with the port and channel identifiers in the
following format:

```typescript
prefix + denom = {destPortN}/{destChannelN}/.../{destPort0}/{destChannel0}/denom
```

Example: transfering `100 uatom` from port `HubPort` and channel `HubChannel` on the Hub to
Ethermint's port `EthermintPort` and channel `EthermintChannel` results in `10
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
EthermintPort/EthermintChannel/uatom`, where `EthermintPort/EthermintChannel/uatom` is the new
denomination on the receiving chain.

In the case those tokens are transfered back to the Hub (i.e the **source** chain), the prefix is
trimmed and the token denomination updated to the original one.

### Problem

The problem of adding additional information to the coin denomination is twofold:

1. The ever increasing length if tokens are transfered to zones other than the source:

If a token is transfered `n` times via IBC to a sink chain, the token denom will contain `n` pairs
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
of prefixes, as shown on the format example above. This is supposes a problem because, while port
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
and channel identifiers don't have a cap on the maximum lenght, the SDK `Coin` type only accepts
denoms up to 64 characters.

This can result undesired behaviours such as tokens not being abled to be transfered to multiple
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
sink chains if the denomination exceeds the lenght or unexpected `panics` due to denomination
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
validation on the receiving chain.

2. The existence of special characters and upercase letters on the denomination:
fedekunze marked this conversation as resolved.
Show resolved Hide resolved

In the SDK everytime a `Coin` is initialized trhough the constructor function `NewCoin`, a validation
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
of a coin's denom is performed according to a
[Regex](https://github.com/cosmos/cosmos-sdk/blob/a940214a4923a3bf9a9161cd14bd3072299cd0c9/types/coin.go#L583),
where only lowercase alphanumeric characters are accepted. While this is desirable for native denoms
to keep a clean UX, it supposes a challenge for IBC as ports and channels might be randomly
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
generated with special carracters and uppercases as per the [ICS 024 - Host
fedekunze marked this conversation as resolved.
Show resolved Hide resolved
Requirements](https://github.com/cosmos/ics/tree/master/spec/ics-024-host-requirements#paths-identifiers-separators)
specification.

## Decision

Introduce a new `Trace` field to the SDK's `Coin` type so that the two problems are mitigated.

<!-- TODO: change field to metadata -->

```protobuf
// Coin defines a token with a denomination and an amount.
//
// NOTE: The amount field is an Int which implements the custom method
// signatures required by gogoproto.
message Coin {
option (gogoproto.equal) = true;

string denom = 1;
string amount = 2 [(gogoproto.customtype) = "Int", (gogoproto.nullable) = false];
// trace the origin of the token. Every time a Coin is transferred to a chain that's not the souce
// of the token, a new item is inserted to the first position.
repeated Trace trace = 3;
Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the elaborate and well throughout ADR @fedekunze, but I can see that I'll already have concerns with this because we're conflating concerns and use-cases w/ IBC. Specifically, I do not believe trace should be a first-class citizen field of Coin. Please consider instead using some notion of metadata.

Copy link
Member

Choose a reason for hiding this comment

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

I agree that we should use metadata and not add this to Coin itself. @fedekunze I have some ideas on how to address this more generally and will write something up.

Copy link
Member

@aaronc aaronc Jul 10, 2020

Choose a reason for hiding this comment

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

So I realize what I have in mind will be a larger ADR that also covers supply. I'm hoping to get to that relatively soon as these are things I've thought about for some of Regen's use case which allows for some modules to arbitrarily create approved denom's.

Anyway the gist of it is that from the perspective of the bank module, IBC transfer is just minting or burning coins for some denom which it has the right to manage.

I propose we use prefixes for these denoms such as ibc: or ibc/ and then IBC assigns an auto-generated ID that looks something like ibc:2g8sd6h. Or maybe ibc:atom:2g8sd6h to be more descriptive if the source denom is atom.

Then the Trace information is something that gets managed as metadata by the ibc transfer module. So the ibc transfer keeper would then have a method like DescribeIBCDenom(denom string) IBCDenomMetadata to retrieve the Trace data.

One problem that I pointed out in the call is that balances are indexed by denom. So adding Trace would break that in addition polluting any balances with all of that metadata. Instead we can just treat denoms as dumb identifiers which are fully described by their metadata.

To take it a step further, I would restrict which modules can mint/burn which denoms. So x/mint would get rights to atom, x/ibc-transfer would mange the whole ibc:* prefix, etc. But that gets into supply which I'd love to address too, but later after stargate.

Copy link
Contributor

Choose a reason for hiding this comment

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

This makes sense, although for now (IBC 1.0) I think we should do the simplest thing which solves our main problem, and hash the denominations in the 20-transfer module to allow for arbitrary port/channel paths, and keep a lookup table so that we can lookup the port(s) & channel(s) from the denomination.

}

// Trace defines a origin tracing logic for fungible token cross-chain token transfers through
// IBC (as specified per ICS20).
message Trace {
// destination chain port identifier
string port_id = 1 [(gogoproto.moretags) = "yaml:\"port_id\""];
// destination chain channel identifier
string channel_id = 2 [(gogoproto.moretags) = "yaml:\"channel_id\""];
}
```

To prevent breaking the `NewCoin` constructor, a separate `NewCoinWithTrace` function will be
created.

```go

// NewCoinWithTrace creates a new coin with .
func NewCoinWithTrace(denom string, amount Int, traces ...Trace) Coin {
coin := NewCoin(denom, amount)

for _, trace := range traces {
if err := validateTrace(trace); err != nil {
panic(err)
}
}

coin.Trace = traces
return coin
}
```

To transfer tokens to a sink chain via IBC, `InsertTrace` can be used:

```go
// InsertTrace validates the destination port and channel identifiers and inserts a Trace
// insance to the first position of the list.
func (coin *Coin) InsertTrace(portID, channelID string) error {
if err := validatePortID(portID); err != nil {
return err
}

if err := validateChannelID(channelID); err != nil {
return err
}

coin.Trace = append([]Trace{NewTrace(portID, channelID)}, coin.Trace...)
return nil
}
```

To delete a trace instance, the `PopTrace` utity function can be used:

```go
// PopTrace removes and returns the first trace item from the list. If the list is empty
// an error is returned instead.
func (coin *Coin) PopTrace() (Trace, error) {
if len(coin.Trace) == 0 {
return Trace{}, errors.New("trace list is empty")
}

trace := coin.Trace[0]
coin.Trace = coin.Trace[1:]
return trace, nil
}
```

<!-- TODO: updates to ICS20 -->

### Positive

- Clearer separation of the origin tracing behaviour of the token (transfer prefix) from the original
`Coin` denomination
- Consistent validation of `Coin` fields
- Prevents clients from having to strip the denomination
- Cleaner `Coin` denominations for IBC instead of prefixed ones

### Negative

- `Coin` metadata size is not bounded, which might result in a significant increase of the size per
`Coin` compared with the current implementation.

### Neutral

- Additional field to the `Coin` type
- Slight difference with the ICS20 spec

## References

- [ICS 20 - Fungible token
transfer](https://github.com/cosmos/ics/tree/master/spec/ics-020-fungible-token-transfer)