@@ -21,6 +21,8 @@ import (
21
21
22
22
// The code in this file is removed in ibc v9. It is copied from ibc v8 to here in order to support the migration to v9
23
23
24
+ // ReceiverChainIsSource returns true if the denomination originally came
25
+ // from the receiving chain and false otherwise.
24
26
func ReceiverChainIsSource (sourcePort , sourceChannel , denom string ) bool {
25
27
// The prefix passed in should contain the SourcePort and SourceChannel.
26
28
// If the receiver chain originally sent the token to the sender chain
@@ -31,61 +33,89 @@ func ReceiverChainIsSource(sourcePort, sourceChannel, denom string) bool {
31
33
return strings .HasPrefix (denom , voucherPrefix )
32
34
}
33
35
36
+ // GetDenomPrefix returns the receiving denomination prefix
34
37
func GetDenomPrefix (portID , channelID string ) string {
35
38
return fmt .Sprintf ("%s/%s/" , portID , channelID )
36
39
}
37
40
41
+ // GetPrefixedDenom returns the denomination with the portID and channelID prefixed
38
42
func GetPrefixedDenom (portID , channelID , baseDenom string ) string {
39
43
return fmt .Sprintf ("%s/%s/%s" , portID , channelID , baseDenom )
40
44
}
41
45
46
+ // DenomTrace contains the base denomination for ICS20 fungible tokens and the
47
+ // source tracing information path.
42
48
type DenomTrace struct {
43
- Path string
44
- BaseDenom string
49
+ // path defines the chain of port/channel identifiers used for tracing the
50
+ // source of the fungible token.
51
+ Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"`
52
+ // base denomination of the relayed fungible token.
53
+ BaseDenom string `protobuf:"bytes,2,opt,name=base_denom,json=baseDenom,proto3" json:"base_denom,omitempty"`
45
54
}
46
55
47
56
const DenomPrefix = "ibc"
48
57
58
+ // ParseDenomTrace parses a string with the ibc prefix (denom trace) and the base denomination
59
+ // into a DenomTrace type.
60
+ //
61
+ // Examples:
62
+ //
63
+ // - "portidone/channel-0/uatom" => DenomTrace{Path: "portidone/channel-0", BaseDenom: "uatom"}
64
+ // - "portidone/channel-0/portidtwo/channel-1/uatom" => DenomTrace{Path: "portidone/channel-0/portidtwo/channel-1", BaseDenom: "uatom"}
65
+ // - "portidone/channel-0/gamm/pool/1" => DenomTrace{Path: "portidone/channel-0", BaseDenom: "gamm/pool/1"}
66
+ // - "gamm/pool/1" => DenomTrace{Path: "", BaseDenom: "gamm/pool/1"}
67
+ // - "uatom" => DenomTrace{Path: "", BaseDenom: "uatom"}
68
+ func ParseDenomTrace (rawDenom string ) DenomTrace {
69
+ denomSplit := strings .Split (rawDenom , "/" )
70
+
71
+ if denomSplit [0 ] == rawDenom {
72
+ return DenomTrace {
73
+ Path : "" ,
74
+ BaseDenom : rawDenom ,
75
+ }
76
+ }
77
+
78
+ path , baseDenom := extractPathAndBaseFromFullDenom (denomSplit )
79
+ return DenomTrace {
80
+ Path : path ,
81
+ BaseDenom : baseDenom ,
82
+ }
83
+ }
84
+
85
+ // Hash returns the hex bytes of the SHA256 hash of the DenomTrace fields using the following formula:
86
+ //
87
+ // hash = sha256(tracePath + "/" + baseDenom)
49
88
func (dt DenomTrace ) Hash () tmbytes.HexBytes {
50
89
hash := sha256 .Sum256 ([]byte (dt .GetFullDenomPath ()))
51
90
return hash [:]
52
91
}
53
92
93
+ // GetPrefix returns the receiving denomination prefix composed by the trace info and a separator.
54
94
func (dt DenomTrace ) GetPrefix () string {
55
95
return dt .Path + "/"
56
96
}
57
97
58
- func (dt DenomTrace ) GetFullDenomPath () string {
59
- if dt .Path == "" {
60
- return dt .BaseDenom
61
- }
62
- return dt .GetPrefix () + dt .BaseDenom
63
- }
64
-
98
+ // IBCDenom a coin denomination for an ICS20 fungible token in the format
99
+ // 'ibc/{hash(tracePath + baseDenom)}'. If the trace is empty, it will return the base denomination.
65
100
func (dt DenomTrace ) IBCDenom () string {
66
101
if dt .Path != "" {
67
102
return fmt .Sprintf ("%s/%s" , DenomPrefix , dt .Hash ())
68
103
}
69
104
return dt .BaseDenom
70
105
}
71
106
72
- func ParseDenomTrace (rawDenom string ) DenomTrace {
73
- denomSplit := strings .Split (rawDenom , "/" )
74
-
75
- if denomSplit [0 ] == rawDenom {
76
- return DenomTrace {
77
- Path : "" ,
78
- BaseDenom : rawDenom ,
79
- }
80
- }
81
-
82
- path , baseDenom := extractPathAndBaseFromFullDenom (denomSplit )
83
- return DenomTrace {
84
- Path : path ,
85
- BaseDenom : baseDenom ,
107
+ // GetFullDenomPath returns the full denomination according to the ICS20 specification:
108
+ // tracePath + "/" + baseDenom
109
+ // If there exists no trace then the base denomination is returned.
110
+ func (dt DenomTrace ) GetFullDenomPath () string {
111
+ if dt .Path == "" {
112
+ return dt .BaseDenom
86
113
}
114
+ return dt .GetPrefix () + dt .BaseDenom
87
115
}
88
116
117
+ // extractPathAndBaseFromFullDenom returns the trace path and the base denom from
118
+ // the elements that constitute the complete denom.
89
119
func extractPathAndBaseFromFullDenom (fullDenomItems []string ) (string , string ) {
90
120
var (
91
121
pathSlice []string
@@ -117,6 +147,10 @@ func extractPathAndBaseFromFullDenom(fullDenomItems []string) (string, string) {
117
147
return path , baseDenom
118
148
}
119
149
150
+ // ValidateIBCDenom validates that the given denomination is either:
151
+ //
152
+ // - A valid base denomination (eg: 'uatom' or 'gamm/pool/1' as in https://github.com/cosmos/ibc-go/issues/894)
153
+ // - A valid fungible token representation (i.e 'ibc/{hash}') per ADR 001 https://github.com/cosmos/ibc-go/blob/main/docs/architecture/adr-001-coin-source-tracing.md
120
154
func ValidateIBCDenom (denom string ) error {
121
155
if err := sdk .ValidateDenom (denom ); err != nil {
122
156
return err
0 commit comments