-
Notifications
You must be signed in to change notification settings - Fork 229
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
support non-Cosmos addresses in ChainHub #11007
base: master
Are you sure you want to change the base?
Conversation
Deploying agoric-sdk with
|
Latest commit: |
79aeda0
|
Status: | ✅ Deploy successful! |
Preview URL: | https://f977a34a.agoric-sdk.pages.dev |
Branch Preview URL: | https://250-non-cosmos.agoric-sdk.pages.dev |
f486d77
to
e7aebd1
Compare
chainId: string; | ||
// TODO should we call this accountAddress to align with CAIP-10? | ||
/** The address value used on-chain */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vitalik has been calling this a "chain-specific address" ethereum/ERCs#735
c4096c3
to
24525be
Compare
if (parts.length >= 3) { | ||
return { | ||
chainId: `${parts[0]}:${parts[1]}`, | ||
accountAddress: parts.slice(2).join(':'), // Handles cases where the address contains colons |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we expect this to be the case (colon in address value), or are we being defensive? Maybe better to throw if the length is > 3?
* agoric1megzytg65cyrgzs6fvzxgrcqvwwl7ugpt62346 | ||
* cosmosvaloper1npm9gvss52mlmk | ||
*/ | ||
export type CosmosAddress = `${string}1${string}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should call this Bech32Address
, or even just Bech32
? For Ethereum, we could do:
export type (Hex|HexAddress) = `0x${string}`
Maybe too hungarian, but bech32
is also used outside of cosmos
// TODO should this be AccountId to align with CAIP-10? | ||
/** An address on some blockchain, e.g., cosmos, eth, etc. */ | ||
/** à la CAIP-2 */ | ||
export type ChainId = `${string}:${string}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does this work for the backwards compat case? i.e. agoric-3
instead of cosmos:agoric-3
? The answer might be it doesn't, and this is probably fine, but looking to better understand
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One of these is always namespaced. CosmosChainAddress['chainId']
is just agoric-3
.
Looks like this comment was reviewing by commit (good idea). In another commit it was changed to ScopedChainId
to clarify.
@@ -191,7 +191,6 @@ export const prepareIcaAccountKit = (zone, { watch, asVow }) => | |||
this.state.chainAddress = harden({ | |||
value: address || UNPARSABLE_CHAIN_ADDRESS, | |||
chainId: this.state.chainId, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would we want to prefix this with cosmos
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had considered that but it would make more cases to handle. In CosmosChainAddress
, chainId
is always within the cosmos
namespace. The CAIP-10 form always has a namespace.
destination = | ||
typeof destination === 'string' | ||
? chainHub.makeChainAddress(destination) | ||
: destination; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
iiuc - destination can be a non-cosmos chain?
I would expect makeTransferRoute
to throw if it sees a non-cosmos namespace. is this path tested?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. This is just for IBC. I'll handle make that more explicit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh good, it was already checking
assert.equal(namespace, 'cosmos'); |
but I'll leave a comment here to make the reader aware
@@ -200,7 +229,7 @@ export interface OrchestrationAccountCommon { | |||
* the transfer is rejected (insufficient funds, timeout) | |||
*/ | |||
transfer: ( | |||
destination: ChainAddress, | |||
destination: AccountId | CosmosChainAddress, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
destination: AccountId | CosmosChainAddress, | |
destination: AccountIdable, |
3add2cf
to
8a4659b
Compare
Deploying agoric-sdk with
|
Latest commit: |
8a4659b
|
Status: | ✅ Deploy successful! |
Preview URL: | https://37eb86ad.agoric-sdk.pages.dev |
Branch Preview URL: | https://250-non-cosmos.agoric-sdk.pages.dev |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm uneasy with using syntax that endo patterns can't verify.
In particular, there a few places where the static and dynamic checks don't line up here, and I'm not confident that it's defensively correct in all the relevant cases.
If we're going to use special string syntax, let's please use string
as the argument type where the pattern guard says M.string()
and then use assertAccountId(x)
or the like to validate inside the method.
const amt: DenomAmount = harden({ denom: uusdcOnAgoric, value: 100n }); | ||
t.deepEqual(chainHub.makeTransferRoute(dest, amt, 'agoric'), { | ||
receiver: 'noble1234', | ||
sourceChannel: 'channel-62', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be sure that 'channel-62'
is right, I'd have to look it up in fetched-chain-info.
To make it more handy, how about adding something like:
const agoricToNoble = knownChains.agoric.connections['noble-1'].transferChannel;
t.is(agoricToNoble.id, 'channel-62');
}, | ||
}, | ||
{ | ||
encoding: Object @match:string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can the encoding of a cosmos address be anything other than bech32
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the pattern could express that.
and the corresponding static type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given it's ignored, what is the value of erroring when it's not "bech32"?
The corresponding static type doesn't have it at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point. never mind.
@@ -547,7 +557,7 @@ export const makeChainHub = (zone, agoricNames, vowTools) => { | |||
* | |||
* XXX consider accepting AmountArg #10449 | |||
* | |||
* @param {CosmosChainAddress} destination | |||
* @param {AccountIdable} destination |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The pattern guard doesn't guarantee the AccountIdable
type.
return `cosmos:${reference}:${accountAddress}`; | ||
}, | ||
/** | ||
* @param {AccountId | Bech32Address} partialId CAIP-10 account ID or a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The M.string()
dynamic check doesn't guarantee this static type.
@@ -576,6 +586,11 @@ export const makeChainHub = (zone, agoricNames, vowTools) => { | |||
|
|||
const holdingChainId = chainInfos.get(srcChainName).chainId; | |||
|
|||
destination = | |||
typeof destination === 'string' | |||
? chainHub.makeChainAddress(destination) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
makeChainAddress
takes a AccountId | Bech32Address
but only M.string()
is guaranteed by dynamic checks so far.
return /** @type {AccountId} */ (partialId); | ||
} | ||
|
||
const accountAddress = /** @type {Bech32Address} */ (partialId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what justifies this cast? partialId
is only statically known to be a string
, AFAICT.
const CAIP10_ID = | ||
'cosmos:osmosis-1:osmo1ht7u569vpuryp6utadsydcne9ckeh2v8dkd38v5hptjl3u2ewppqc6kzgd'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if given a chainId that's different from the one know to the chainHub for this bech32 prefix? e.g. cosmos:osmosis-2:osmo1ht...
.
If that doesn't throw, it seems like there's a bit of a hazard that callers will forget to keep that possibility in mind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good case to define and test. ChainHub is only keeping track of the Cosmos chain-id when none is specified. If someone specifies osmosis-1
, that's valid, even if ChainHub says "when you see osmo1
without a chain-id use osmosis-3
". Right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a coherent design, yes.
8a4659b
to
79aeda0
Compare
refs: https://github.com/Agoric/agoric-private/issues/250
Description
Introduces new types and guards to use CAIP-2 and CAIP-10.
Maintains backwards compatibility by widening type guards and transforming types as needed.
Security Considerations
none
Scaling Considerations
none
Documentation Considerations
New types will appear in generated docs
Testing Considerations
TODO:
Upgrade Considerations
This has changes for both the API and the contract.
The A3P upgrade test will cover that the contract continue to work with these changes.
The API is kept backwards compatible through widening params and having type aliases.