-
Notifications
You must be signed in to change notification settings - Fork 228
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9114 from Agoric/9042-stake-atom
feat: create chain account (ica)
- Loading branch information
Showing
20 changed files
with
968 additions
and
3 deletions.
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'); | ||
}); |
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.