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

Implement 04-upgrade spec #259

Merged
merged 5 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
98 changes: 59 additions & 39 deletions .gas-snapshot
Original file line number Diff line number Diff line change
@@ -1,51 +1,71 @@
IBCMockAppTest:testHandshake() (gas: 3433206)
IBCMockAppTest:testHandshakeBetweenDifferentPorts() (gas: 2539275)
IBCMockAppTest:testPacketRelay() (gas: 9417242)
IBCMockAppTest:testPacketTimeout() (gas: 2872300)
IBCTest:testBenchmarkCreateMockClient() (gas: 209365)
IBCMockAppTest:testHandshake() (gas: 3537520)
IBCMockAppTest:testHandshakeBetweenDifferentPorts() (gas: 2644408)
IBCMockAppTest:testPacketRelay() (gas: 9584548)
IBCMockAppTest:testPacketTimeout() (gas: 2981201)
IBCTest:testBenchmarkCreateMockClient() (gas: 209410)
IBCTest:testBenchmarkLCUpdateMockClient() (gas: 39945)
IBCTest:testBenchmarkRecvPacket() (gas: 129941)
IBCTest:testBenchmarkSendPacket() (gas: 81008)
IBCTest:testBenchmarkRecvPacket() (gas: 133353)
IBCTest:testBenchmarkSendPacket() (gas: 80964)
IBCTest:testBenchmarkUpdateMockClient() (gas: 137373)
IBCTest:testToUint128((uint64,uint64)) (runs: 256, μ: 947, ~: 947)
TestICS02:testCreateClient() (gas: 23070967)
TestICS02:testInvalidCreateClient() (gas: 22920564)
TestICS02:testInvalidUpdateClient() (gas: 22922411)
TestICS02:testRegisterClient() (gas: 22665440)
TestICS02:testRegisterClientDuplicatedClientType() (gas: 22648665)
TestICS02:testRegisterClientInvalidClientType() (gas: 22632794)
TestICS02:testUpdateClient() (gas: 23087963)
TestICS03Handshake:testConnOpenAck() (gas: 1631720)
TestICS03Handshake:testConnOpenConfirm() (gas: 1766228)
TestICS03Handshake:testConnOpenInit() (gas: 1279055)
TestICS03Handshake:testConnOpenTry() (gas: 2160823)
TestICS03Handshake:testInvalidConnOpenAck() (gas: 2031544)
TestICS03Handshake:testInvalidConnOpenConfirm() (gas: 2096106)
TestICS03Handshake:testInvalidConnOpenInit() (gas: 666816)
TestICS03Handshake:testInvalidConnOpenTry() (gas: 2101149)
TestICS02:testCreateClient() (gas: 33302626)
TestICS02:testInvalidCreateClient() (gas: 33152264)
TestICS02:testInvalidUpdateClient() (gas: 33154327)
TestICS02:testRegisterClient() (gas: 32897266)
TestICS02:testRegisterClientDuplicatedClientType() (gas: 32880491)
TestICS02:testRegisterClientInvalidClientType() (gas: 32864530)
TestICS02:testUpdateClient() (gas: 33319687)
TestICS03Handshake:testConnOpenAck() (gas: 1631658)
TestICS03Handshake:testConnOpenConfirm() (gas: 1766077)
TestICS03Handshake:testConnOpenInit() (gas: 1279190)
TestICS03Handshake:testConnOpenTry() (gas: 2160696)
TestICS03Handshake:testInvalidConnOpenAck() (gas: 2031548)
TestICS03Handshake:testInvalidConnOpenConfirm() (gas: 2095798)
TestICS03Handshake:testInvalidConnOpenInit() (gas: 666951)
TestICS03Handshake:testInvalidConnOpenTry() (gas: 2101089)
TestICS03Version:testCopyVersions() (gas: 558658)
TestICS03Version:testFindSupportedVersion() (gas: 19400)
TestICS03Version:testIsSupportedVersion() (gas: 7864)
TestICS03Version:testPickVersion() (gas: 25327)
TestICS03Version:testVerifyProposedVersion() (gas: 11777)
TestICS03Version:testVerifySupportedFeature() (gas: 4153)
TestICS04Handshake:testBindPort() (gas: 37414)
TestICS04Handshake:testChanClose() (gas: 8457966)
TestICS04Handshake:testChanOpenAck() (gas: 2879243)
TestICS04Handshake:testChanOpenConfirm() (gas: 3058457)
TestICS04Handshake:testChanOpenInit() (gas: 2195918)
TestICS04Handshake:testChanOpenTry() (gas: 2653852)
TestICS04Handshake:testInvalidChanOpenAck() (gas: 2060952)
TestICS04Handshake:testInvalidChanOpenConfirm() (gas: 2116580)
TestICS04Handshake:testInvalidChanOpenInit() (gas: 1275939)
TestICS04Handshake:testInvalidChanOpenTry() (gas: 1352198)
TestICS04Packet:testAcknowledgementPacket() (gas: 2276942)
TestICS04Packet:testInvalidSendPacket() (gas: 2274365)
TestICS04Packet:testRecvPacket() (gas: 7645640)
TestICS04Packet:testRecvPacketTimeoutHeight() (gas: 2295912)
TestICS04Packet:testRecvPacketTimeoutTimestamp() (gas: 2305786)
TestICS04Packet:testSendPacket() (gas: 5018609)
TestICS04Packet:testTimeoutOnClose() (gas: 2532922)
TestICS04Handshake:testBindPort() (gas: 37502)
TestICS04Handshake:testChanClose() (gas: 8864072)
TestICS04Handshake:testChanOpenAck() (gas: 2988216)
TestICS04Handshake:testChanOpenConfirm() (gas: 3170513)
TestICS04Handshake:testChanOpenInit() (gas: 2274533)
TestICS04Handshake:testChanOpenTry() (gas: 2759774)
TestICS04Handshake:testInvalidChanOpenAck() (gas: 2115402)
TestICS04Handshake:testInvalidChanOpenConfirm() (gas: 2171859)
TestICS04Handshake:testInvalidChanOpenInit() (gas: 1299857)
TestICS04Handshake:testInvalidChanOpenTry() (gas: 1378320)
TestICS04Packet:testAcknowledgementPacket() (gas: 2393006)
TestICS04Packet:testInvalidSendPacket() (gas: 2385887)
TestICS04Packet:testRecvPacket() (gas: 7941501)
TestICS04Packet:testRecvPacketTimeoutHeight() (gas: 2411677)
TestICS04Packet:testRecvPacketTimeoutTimestamp() (gas: 2421551)
TestICS04Packet:testSendPacket() (gas: 5160796)
TestICS04Packet:testTimeoutOnClose() (gas: 2654567)
TestICS04Upgrade:testUpgradeAuthorityCancel() (gas: 32899652)
TestICS04Upgrade:testUpgradeCannotCancelWithOldErrorReceipt() (gas: 2648059)
TestICS04Upgrade:testUpgradeCannotRecvNextUpgradePacket() (gas: 3322208)
TestICS04Upgrade:testUpgradeCounterpartyAdvanceNextSequenceBeforeOpen() (gas: 3402742)
TestICS04Upgrade:testUpgradeCrossingHelloIncompatibleProposals() (gas: 3312033)
TestICS04Upgrade:testUpgradeFull() (gas: 34308220)
TestICS04Upgrade:testUpgradeInit() (gas: 2362479)
TestICS04Upgrade:testUpgradeNoChanges() (gas: 1950920)
TestICS04Upgrade:testUpgradeOutOfSync() (gas: 3051844)
TestICS04Upgrade:testUpgradeRelaySuccessAtCounterpartyFlushComplete() (gas: 3325729)
TestICS04Upgrade:testUpgradeRelaySuccessAtFlushing() (gas: 3522672)
TestICS04Upgrade:testUpgradeSendPacketFailAtFlushingOrFlushComplete() (gas: 2743014)
TestICS04Upgrade:testUpgradeTimeoutAbortAck() (gas: 10509336)
TestICS04Upgrade:testUpgradeTimeoutAbortConfirm() (gas: 11912012)
TestICS04Upgrade:testUpgradeTimeoutUpgrade() (gas: 31027545)
TestICS04Upgrade:testUpgradeToOrdered() (gas: 36895593)
TestICS04Upgrade:testUpgradeToUnordered() (gas: 29370382)
TestICS04UpgradeApp:testUpgradeAuthorizationChanneNotFound() (gas: 37604)
TestICS04UpgradeApp:testUpgradeAuthorizationRePropose() (gas: 2034676)
TestICS04UpgradeApp:testUpgradeAuthorizationRemove() (gas: 1859258)
TestICS20:testAddressToHex(address) (runs: 256, μ: 22676, ~: 22804)
TestICS20:testHexToAddress(string) (runs: 256, μ: 4776, ~: 4734)
TestICS20:testIsEscapedString() (gas: 48979)
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ abigen: build
.PHONY: network-e2e
network-e2e:
$(DOCKER_COMPOSE) -f $(E2E_TEST_COMPOSE_FILE) up --detach --wait testchain0 testchain1
TEST_MNEMONIC=$(TEST_MNEMONIC) $(FORGE) script --legacy --slow --use solc:${SOLC_VERSION} --fork-url http://127.0.0.1:8645 --broadcast \
TEST_MNEMONIC=$(TEST_MNEMONIC) $(FORGE) script --legacy --batch-size 5 --use solc:${SOLC_VERSION} --fork-url http://127.0.0.1:8645 --broadcast \
./tests/foundry/src/Deploy.s.sol
TEST_MNEMONIC=$(TEST_MNEMONIC) $(FORGE) script --legacy --slow --use solc:${SOLC_VERSION} --fork-url http://127.0.0.1:8745 --broadcast \
TEST_MNEMONIC=$(TEST_MNEMONIC) $(FORGE) script --legacy --batch-size 5 --use solc:${SOLC_VERSION} --fork-url http://127.0.0.1:8745 --broadcast \
./tests/foundry/src/Deploy.s.sol

.PHONY: network-down
Expand Down
10 changes: 6 additions & 4 deletions contracts/apps/commons/IBCAppBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ import {Packet} from "../../core/04-channel/IIBCChannel.sol";
import {IIBCModule} from "../../core/26-router/IIBCModule.sol";
import {IIBCModuleErrors} from "../../core/26-router/IIBCModuleErrors.sol";

/**
* @dev Base contract of the IBC App protocol
*/
abstract contract IBCAppBase is Context, IIBCModule, IIBCModuleErrors {
abstract contract AppBase is Context, IIBCModuleErrors {
/**
* @dev Throws if called by any account other than the IBC contract.
*/
Expand All @@ -31,7 +28,12 @@ abstract contract IBCAppBase is Context, IIBCModule, IIBCModuleErrors {
revert IBCModuleInvalidSender(_msgSender());
}
}
}

/**
* @dev Base contract of the IBC App protocol
*/
abstract contract IBCAppBase is AppBase, IIBCModule {
/**
* @dev See IIBCModule-onChanOpenInit
*
Expand Down
5 changes: 3 additions & 2 deletions contracts/apps/mock/IBCMockApp.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ contract IBCMockApp is IBCAppBase, IIBCMockErrors, Ownable {
function onRecvPacket(Packet calldata packet, address)
external
view
virtual
override
onlyIBC
returns (bytes memory acknowledgement)
Expand Down Expand Up @@ -126,13 +127,13 @@ contract IBCMockApp is IBCAppBase, IIBCMockErrors, Ownable {
}
}

function onTimeoutPacket(Packet calldata packet, address) external view override onlyIBC {
function onTimeoutPacket(Packet calldata packet, address) external view virtual override onlyIBC {
if (!closeChannelAllowed) {
revert IBCModuleChannelCloseNotAllowed(packet.sourcePort, packet.sourceChannel);
}
}

function equals(bytes calldata a, bytes memory b) private pure returns (bool) {
function equals(bytes calldata a, bytes memory b) internal pure returns (bool) {
return keccak256(a) == keccak256(b);
}
}
2 changes: 1 addition & 1 deletion contracts/clients/LocalhostClient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ contract LocalhostClient is ILightClient, ILightClientErrors {
ClientState.Data({
latest_height: Height.Data({revision_number: 0, revision_height: uint64(block.number)})
})
),
),
true
);
}
Expand Down
13 changes: 13 additions & 0 deletions contracts/core/03-connection/IBCConnectionLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,19 @@ library IBCConnectionLib {
return verifyProposedVersion(supportedVersion, version);
}

function isSupported(Version.Data[] storage supportedVersions, string memory feature)
internal
view
returns (bool)
{
for (uint256 i = 0; i < supportedVersions.length; i++) {
if (verifySupportedFeature(supportedVersions[i], feature)) {
return true;
}
}
return false;
}

/**
* @dev verifyProposedVersion verifies that the entire feature set in the
* proposed version is supported by this chain. If the feature set is
Expand Down
14 changes: 10 additions & 4 deletions contracts/core/04-channel/IBCChannelHandshake.sol
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,8 @@ contract IBCChannelHandshake is IBCModuleManager, IIBCChannelHandshake, IIBCChan
ordering: msg_.channel.ordering,
counterparty: ChannelCounterparty.Data({port_id: msg_.portId, channel_id: ""}),
connection_hops: getCounterpartyHops(msg_.channel.connection_hops[0]),
version: msg_.counterpartyVersion
version: msg_.counterpartyVersion,
upgrade_sequence: 0
});
verifyChannelState(
connection,
Expand Down Expand Up @@ -166,7 +167,8 @@ contract IBCChannelHandshake is IBCModuleManager, IIBCChannelHandshake, IIBCChan
ordering: channel.ordering,
counterparty: ChannelCounterparty.Data({port_id: msg_.portId, channel_id: msg_.channelId}),
connection_hops: getCounterpartyHops(channel.connection_hops[0]),
version: msg_.counterpartyVersion
version: msg_.counterpartyVersion,
upgrade_sequence: 0
});

verifyChannelState(
Expand Down Expand Up @@ -204,7 +206,8 @@ contract IBCChannelHandshake is IBCModuleManager, IIBCChannelHandshake, IIBCChan
ordering: channel.ordering,
counterparty: ChannelCounterparty.Data({port_id: msg_.portId, channel_id: msg_.channelId}),
connection_hops: getCounterpartyHops(channel.connection_hops[0]),
version: channel.version
version: channel.version,
upgrade_sequence: 0
});
verifyChannelState(
connection,
Expand Down Expand Up @@ -264,7 +267,8 @@ contract IBCChannelHandshake is IBCModuleManager, IIBCChannelHandshake, IIBCChan
ordering: channel.ordering,
counterparty: ChannelCounterparty.Data({port_id: msg_.portId, channel_id: msg_.channelId}),
connection_hops: getCounterpartyHops(channel.connection_hops[0]),
version: channel.version
version: channel.version,
upgrade_sequence: 0
});
verifyChannelState(
connection,
Expand Down Expand Up @@ -301,6 +305,7 @@ contract IBCChannelHandshake is IBCModuleManager, IIBCChannelHandshake, IIBCChan
channel.connection_hops.push(connectionHops[i]);
}
channel.version = version;
channel.upgrade_sequence = 0;
updateChannelCommitment(portId, channelId);
}

Expand Down Expand Up @@ -344,6 +349,7 @@ contract IBCChannelHandshake is IBCModuleManager, IIBCChannelHandshake, IIBCChan
nextSequenceSends[portId][channelId] = 1;
nextSequenceRecvs[portId][channelId] = 1;
nextSequenceAcks[portId][channelId] = 1;
recvStartSequences[portId][channelId].sequence = 1;
commitments[IBCCommitment.nextSequenceRecvCommitmentKey(portId, channelId)] =
keccak256(abi.encodePacked((bytes8(uint64(1)))));
}
Expand Down
6 changes: 6 additions & 0 deletions contracts/core/04-channel/IBCChannelLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ library IBCChannelLib {
}
}

function buildConnectionHops(string memory connectionId) internal pure returns (string[] memory hops) {
hops = new string[](1);
hops[0] = connectionId;
return hops;
}

function toString(Channel.Order order) internal pure returns (string memory) {
if (order == Channel.Order.ORDER_UNORDERED) {
return ORDER_UNORDERED;
Expand Down
44 changes: 36 additions & 8 deletions contracts/core/04-channel/IBCChannelPacketSendRecv.sol
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,20 @@ contract IBCChannelPacketSendRecv is
*/
function recvPacket(MsgPacketRecv calldata msg_) external {
Channel.Data storage channel = channels[msg_.packet.destinationPort][msg_.packet.destinationChannel];
if (channel.state != Channel.State.STATE_OPEN) {
if (channel.state == Channel.State.STATE_OPEN) {} else if (
channel.state == Channel.State.STATE_FLUSHING || channel.state == Channel.State.STATE_FLUSHCOMPLETE
) {
RecvStartSequence storage rseq =
recvStartSequences[msg_.packet.destinationPort][msg_.packet.destinationChannel];
// prevSequence=0 means the channel is not in the process of being upgraded or counterparty has not been upgraded yet
if (rseq.prevSequence != 0) {
if (msg_.packet.sequence >= rseq.sequence) {
revert IBCChannelCannotRecvNextUpgradePacket(msg_.packet.sequence, rseq.sequence);
} else if (msg_.packet.sequence < rseq.prevSequence) {
revert IBCChannelPacketAlreadyProcessInPreviousUpgrade(msg_.packet.sequence, rseq.prevSequence);
}
}
} else {
revert IBCChannelUnexpectedChannelState(channel.state);
}

Expand Down Expand Up @@ -155,6 +168,17 @@ contract IBCChannelPacketSendRecv is
);

if (channel.ordering == Channel.Order.ORDER_UNORDERED) {
if (channel.state == Channel.State.STATE_OPEN) {
if (
msg_.packet.sequence
< recvStartSequences[msg_.packet.destinationPort][msg_.packet.destinationChannel].sequence
) {
revert IBCChannelPacketAlreadyProcessInPreviousUpgrade(
msg_.packet.sequence,
recvStartSequences[msg_.packet.destinationPort][msg_.packet.destinationChannel].sequence
);
}
}
bytes32 commitmentKey = IBCCommitment.packetReceiptCommitmentKeyCalldata(
msg_.packet.destinationPort, msg_.packet.destinationChannel, msg_.packet.sequence
);
Expand Down Expand Up @@ -202,7 +226,9 @@ contract IBCChannelPacketSendRecv is
function acknowledgePacket(MsgPacketAcknowledgement calldata msg_) external {
Channel.Data storage channel = channels[msg_.packet.sourcePort][msg_.packet.sourceChannel];
if (channel.state != Channel.State.STATE_OPEN) {
revert IBCChannelUnexpectedChannelState(channel.state);
if (channel.state != Channel.State.STATE_FLUSHING) {
revert IBCChannelUnexpectedChannelState(channel.state);
}
}

if (keccak256(bytes(msg_.packet.destinationPort)) != keccak256(bytes(channel.counterparty.port_id))) {
Expand Down Expand Up @@ -258,6 +284,14 @@ contract IBCChannelPacketSendRecv is
);
}
nextSequenceAcks[msg_.packet.sourcePort][msg_.packet.sourceChannel]++;
} else if (channel.ordering == Channel.Order.ORDER_UNORDERED) {
if (msg_.packet.sequence < ackStartSequences[msg_.packet.sourcePort][msg_.packet.sourceChannel]) {
revert IBCChannelAckAlreadyProcessedInPreviousUpgrade(
msg_.packet.sequence, ackStartSequences[msg_.packet.sourcePort][msg_.packet.sourceChannel]
);
}
} else {
revert IBCChannelUnknownChannelOrder(channel.ordering);
}

delete commitments[packetCommitmentKey];
Expand Down Expand Up @@ -331,12 +365,6 @@ contract IBCChannelPacketSendRecv is
}
}

function buildConnectionHops(string memory connectionId) private pure returns (string[] memory hops) {
hops = new string[](1);
hops[0] = connectionId;
return hops;
}

function uint64ToBigEndianBytes(uint64 v) private pure returns (bytes memory) {
return abi.encodePacked(bytes8(v));
}
Expand Down
12 changes: 4 additions & 8 deletions contracts/core/04-channel/IBCChannelPacketTimeout.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {ConnectionEnd} from "../../proto/Connection.sol";
import {Channel, ChannelCounterparty} from "../../proto/Channel.sol";
import {ILightClient} from "../02-client/ILightClient.sol";
import {IBCHeight} from "../02-client/IBCHeight.sol";
import {IBCChannelLib} from "./IBCChannelLib.sol";
import {IBCCommitment} from "../24-host/IBCCommitment.sol";
import {IBCModuleManager} from "../26-router/IBCModuleManager.sol";
import {IIBCChannelPacketTimeout} from "./IIBCChannel.sol";
Expand Down Expand Up @@ -182,8 +183,9 @@ contract IBCChannelPacketTimeout is IBCModuleManager, IIBCChannelPacketTimeout,
port_id: msg_.packet.sourcePort,
channel_id: msg_.packet.sourceChannel
}),
connection_hops: buildConnectionHops(connection.counterparty.connection_id),
version: channel.version
connection_hops: IBCChannelLib.buildConnectionHops(connection.counterparty.connection_id),
version: channel.version,
upgrade_sequence: msg_.counterpartyUpgradeSequence
});
if (
!client.verifyMembership(
Expand Down Expand Up @@ -276,12 +278,6 @@ contract IBCChannelPacketTimeout is IBCModuleManager, IIBCChannelPacketTimeout,
}
}

function buildConnectionHops(string memory connectionId) private pure returns (string[] memory hops) {
hops = new string[](1);
hops[0] = connectionId;
return hops;
}

function uint64ToBigEndianBytes(uint64 v) private pure returns (bytes memory) {
return abi.encodePacked(bytes8(v));
}
Expand Down
Loading
Loading