-
Notifications
You must be signed in to change notification settings - Fork 228
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
feat: create chain account (ica) #9114
Merged
+968
−3
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
477cbaf
test(ibc): add bootstrap fixtures for ics27-1 mocking
0xpatrickdev 39b73d5
feat(orchestration): add makeICAConnectionAddress and parseAddress utils
0xpatrickdev ba75ed6
feat(orchestration): create ChainAccount
0xpatrickdev 82f1901
feat(orchestration): add stakeAtom example contract
0xpatrickdev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 89 additions & 0 deletions
89
packages/boot/test/bootstrapTests/test-vat-orchestration.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { test as anyTest } from '@agoric/zoe/tools/prepare-test-env-ava.js'; | ||
import type { ExecutionContext, TestFn } from 'ava'; | ||
import { M, matches } from '@endo/patterns'; | ||
import { makeWalletFactoryContext } from './walletFactory.ts'; | ||
|
||
const makeTestContext = async (t: ExecutionContext) => | ||
makeWalletFactoryContext(t); | ||
|
||
type DefaultTestContext = Awaited<ReturnType<typeof makeTestContext>>; | ||
const test: TestFn<DefaultTestContext> = anyTest; | ||
|
||
test.before(async t => { | ||
t.context = await makeTestContext(t); | ||
|
||
async function setupDeps() { | ||
const { | ||
buildProposal, | ||
evalProposal, | ||
runUtils: { EV }, | ||
} = t.context; | ||
/** ensure network, ibc, and orchestration are available */ | ||
await evalProposal( | ||
buildProposal('@agoric/builders/scripts/vats/init-network.js'), | ||
); | ||
await evalProposal( | ||
buildProposal('@agoric/builders/scripts/vats/init-orchestration.js'), | ||
); | ||
const vatStore = await EV.vat('bootstrap').consumeItem('vatStore'); | ||
t.true(await EV(vatStore).has('ibc'), 'ibc'); | ||
t.true(await EV(vatStore).has('network'), 'network'); | ||
t.true(await EV(vatStore).has('orchestration'), 'orchestration'); | ||
} | ||
|
||
await setupDeps(); | ||
}); | ||
|
||
test.after.always(t => t.context.shutdown?.()); | ||
|
||
test('createAccount returns an ICA connection', async t => { | ||
const { | ||
runUtils: { EV }, | ||
} = t.context; | ||
|
||
const orchestration = await EV.vat('bootstrap').consumeItem('orchestration'); | ||
|
||
const account = await EV(orchestration).createAccount( | ||
'connection-0', | ||
'connection-0', | ||
); | ||
t.truthy(account, 'createAccount returns an account'); | ||
t.truthy( | ||
matches(account, M.remotable('ChainAccount')), | ||
'account is a remotable', | ||
); | ||
const [remoteAddress, localAddress, accountAddress, port] = await Promise.all( | ||
[ | ||
EV(account).getRemoteAddress(), | ||
EV(account).getLocalAddress(), | ||
EV(account).getAccountAddress(), | ||
EV(account).getPort(), | ||
], | ||
); | ||
t.regex(remoteAddress, /icahost/); | ||
t.regex(localAddress, /icacontroller/); | ||
t.regex(accountAddress, /osmo1/); | ||
t.truthy(matches(port, M.remotable('Port'))); | ||
t.log('ICA Account Addresses', { | ||
remoteAddress, | ||
localAddress, | ||
accountAddress, | ||
}); | ||
}); | ||
|
||
test('ICA connection can be closed', async t => { | ||
const { | ||
runUtils: { EV }, | ||
} = t.context; | ||
|
||
const orchestration = await EV.vat('bootstrap').consumeItem('orchestration'); | ||
|
||
const account = await EV(orchestration).createAccount( | ||
'connection-0', | ||
'connection-0', | ||
); | ||
t.truthy(account, 'createAccount returns an account'); | ||
|
||
const res = await EV(account).close(); | ||
t.is(res, 'Connection closed'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how about trying to use it after it's closed and checking that it throws? |
||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
|
||
# ICS-27 Interchain Accounts | ||
|
||
Sequence diagrams for Interchain Accounts based on [ics-027-interchain-accounts/README.md#9ffb1d2](https://github.com/cosmos/ibc/blob/9ffb1d26d3018b6efda546189ec7e43d56d23da3/spec/app/ics-027-interchain-accounts/README.md). | ||
|
||
### IBC Connection Creation | ||
|
||
_Prerequisite to creating a channel._ | ||
|
||
```mermaid | ||
sequenceDiagram | ||
participant CC as Chain A | ||
participant R as Relayer | ||
participant HC as Chain B | ||
|
||
CC->>R: ConnOpenInit(ClientId, CounterpartyClientId, Version) | ||
R->>HC: ConnOpenTry(ClientId, CounterpartyClientId, Version, CounterpartyVersion) | ||
HC-->>R: ConnOpenTry(Version) | ||
R->>CC: ConnOpenAck(ConnectionId, Version) | ||
CC-->>R: ConnOpenAck | ||
R->>HC: ConnOpenConfirm(ConnectionId) | ||
``` | ||
|
||
Mock Testing: | ||
- on `ConnOpenInit`, return `ConnOpenAck` | ||
|
||
### ICA Channel Creation | ||
|
||
```mermaid | ||
sequenceDiagram | ||
participant CC as Controller Chain | ||
participant R as Relayer | ||
participant HC as Host Chain | ||
|
||
CC->>CC: RegisterInterchainAccount() | ||
CC->>R: ChannelOpenInit(Order, ConnectionHops, PortIdentifier, ChannelIdentifier, Version) | ||
R->>HC: ChannelOpenTry(Order, ConnectionHops, PortIdentifier, ChannelIdentifier, Version) | ||
HC->>HC: RegisterInterchainAccount(CounterpartyPortIdentifier) | ||
HC-->>R: ChannelOpenTry(Version) | ||
R->>CC: ChannelOpenAck(PortIdentifier, ChannelIdentifier, CounterpartyVersion) | ||
CC->>CC: SetInterchainAccountAddress(PortID, Address) | ||
CC->>CC: SetActiveChannelID(PortIdentifier, ConnectionID, ChannelIdentifier) | ||
CC-->>R: ChannelOpenAck | ||
R->>HC: ChannelOpenConfirm(PortIdentifier, ChannelIdentifier) | ||
HC->>HC: SetActiveChannelID(CounterpartyPortIdentifier, ConnectionID, ChannelIdentifier) | ||
``` | ||
|
||
Mock Testing: | ||
- on `ChannelOpenInit`, return `ChannelOpenAck` | ||
|
||
### ICA Transaction | ||
|
||
```mermaid | ||
sequenceDiagram | ||
participant CC as Controller Chain | ||
participant R as Relayer | ||
participant HC as Host Chain | ||
|
||
CC->>R: SendPacket(PacketData) | ||
R->>HC: onRecvPacket(Packet) | ||
HC->>HC: Deserialize and validate packet data | ||
alt Successful deserialization and validation | ||
HC->>HC: AuthenticateTx(msgs) | ||
HC->>HC: ExecuteTx(msgs) | ||
HC-->>R: Acknowledgement(result) | ||
else Error | ||
HC-->>R: ErrorAcknowledgement(error) | ||
end | ||
R->>CC: onAcknowledgePacket(Packet, Acknowledgement) | ||
CC->>CC: Handle acknowledgement | ||
``` | ||
|
||
Mock Testing: | ||
- on `SendPacket`, return `onAcknowledgePacket` | ||
|
||
|
||
### ICA Channel Reactivation | ||
|
||
```mermaid | ||
sequenceDiagram | ||
participant CC as Controller Chain | ||
participant R as Relayer | ||
participant HC as Host Chain | ||
|
||
Note over CC,HC: Existing ICA channel expires or closes | ||
CC->>CC: Channel closes or times out | ||
CC->>R: ChannelOpenInit(Order, ConnectionHops, PortIdentifier, ChannelIdentifier, Version) | ||
Note right of CC: Reusing the same PortIdentifier and ConnectionID | ||
R->>HC: ChannelOpenTry(Order, ConnectionHops, PortIdentifier, ChannelIdentifier, Version) | ||
HC->>HC: Verify PortIdentifier and ConnectionID match the previous active channel | ||
HC->>HC: Verify the channel is in CLOSED state | ||
HC->>HC: Verify the new channel has the same order and version as the previous channel | ||
HC-->>R: ChannelOpenTry(Version) | ||
R->>CC: ChannelOpenAck(PortIdentifier, ChannelIdentifier, CounterpartyVersion) | ||
CC->>CC: Verify the CounterpartyVersion matches the previous active channel | ||
CC->>CC: SetActiveChannelID(PortIdentifier, ConnectionID, ChannelIdentifier) | ||
CC-->>R: ChannelOpenAck | ||
R->>HC: ChannelOpenConfirm(PortIdentifier, ChannelIdentifier) | ||
HC->>HC: SetActiveChannelID(CounterpartyPortIdentifier, ConnectionID, ChannelIdentifier) | ||
``` | ||
|
||
Mock Testing: | ||
- on `ChannelOpenInit`, return `ChannelOpenAck` | ||
- n.b. testing should verify `SetActiveChannelID` flow on CC side | ||
|
||
|
||
### Testing Mocks Summary | ||
|
||
- IBC Connection Creation: on ConnOpenInit, return ConnOpenAck | ||
- ICA Channel Creation: on ChannelOpenInit, return ChannelOpenAck | ||
- ICA Transaction: on SendPacket, return onAcknowledgePacket | ||
- ICA Channel Reactivation: on ChannelOpenInit, return ChannelOpenAck | ||
- testing should verify SetActiveChannelID flow on CC side |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/** | ||
* mock bridgeInbound events for ICA (ICS-27) flow | ||
* see [./ics27-1.md](./ics27-1.md) for more details | ||
* | ||
* sourced from [@agoric/vats/test/test-network.js](https://github.com/Agoric/agoric-sdk/blob/4601a1ab65a0c36fbfbfcc1fa59e83ee10a1c996/packages/vats/test/test-network.js) | ||
* and end e2e testing with sim chains (v16: IBC fromBridge logs) | ||
*/ | ||
export const icaMocks = { | ||
startChannelOpenInit: { | ||
// ICA Channel Creation | ||
channelOpenAck: obj => ({ | ||
type: 'IBC_EVENT', | ||
blockHeight: 99, | ||
blockTime: 1711571357, | ||
event: 'channelOpenAck', | ||
portID: obj.packet.source_port, | ||
channelID: 'channel-0', | ||
counterparty: { | ||
port_id: obj.packet.destination_port, | ||
channel_id: 'channel-1', | ||
}, | ||
counterpartyVersion: | ||
'{"version":"ics27-1","controllerConnectionId":"connection-0","hostConnectionId":"connection-0","address":"osmo1234","encoding":"proto3","txType":"sdk_multi_msg"}', | ||
connectionHops: obj.hops, | ||
}), | ||
// XXX channelOpenAckFailure | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { makeHelpers } from '@agoric/deploy-script-support'; | ||
|
||
/** @type {import('@agoric/deploy-script-support/src/externalTypes.js').ProposalBuilder} */ | ||
export const defaultProposalBuilder = async ( | ||
{ publishRef, install }, | ||
options = {}, | ||
) => { | ||
const { | ||
hostConnectionId = 'connection-1', | ||
controllerConnectionId = 'connection-0', | ||
} = options; | ||
return harden({ | ||
sourceSpec: '@agoric/orchestration/src/proposals/start-stakeAtom.js', | ||
getManifestCall: [ | ||
'getManifestForStakeAtom', | ||
{ | ||
installKeys: { | ||
stakeAtom: publishRef( | ||
install( | ||
'@agoric/orchestration/src/contracts/stakeAtom.contract.js', | ||
), | ||
), | ||
}, | ||
hostConnectionId, | ||
controllerConnectionId, | ||
}, | ||
], | ||
}); | ||
}; | ||
|
||
export default async (homeP, endowments) => { | ||
const { writeCoreProposal } = await makeHelpers(homeP, endowments); | ||
await writeCoreProposal('start-stakeAtom', defaultProposalBuilder); | ||
}; |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Is it important that closing a connection frees up resources? If so, is it feasible to check that?
I can imagine it might not be feasible... that any relevant collections are weak / non-enumerable.
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.
These are good questions. I created #9192 to track