Skip to content

Commit

Permalink
add upgrade test for dispatcher from v2.0.0-Rc4 -> v3.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
RnkSngh committed May 7, 2024
1 parent 25e9a3d commit 70df3c0
Show file tree
Hide file tree
Showing 8 changed files with 13,034 additions and 57 deletions.
5 changes: 2 additions & 3 deletions test/Dispatcher/Dispatcher.multiclient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@ pragma solidity ^0.8.15;
import "../../contracts/libs/Ibc.sol";
import {IbcUtils} from "../../contracts/libs/IbcUtils.sol";
import {Mars} from "../../contracts/examples/Mars.sol";
import {DispatcherProofTestUtils} from "./Dispatcher.proof.t.sol";
import {Base} from "../utils/Dispatcher.base.t.sol";
import {DummyLightClient} from "../../contracts/utils/DummyLightClient.sol";
import {OptimisticLightClient} from "../../contracts/core/OptimisticLightClient.sol";
import {ILightClient} from "../../contracts/interfaces/ILightClient.sol";
import "../../contracts/interfaces/IProofVerifier.sol";

contract DispatcherRealProofMultiClient is DispatcherProofTestUtils {
contract DispatcherRealProofMultiClient is Base {
string[] connectionHops0 = ["dummy-connection-1", "dummy-connection-2"];
string[] connectionHops1 = ["connection-2", "connection-1"];
// string[] connectionHops1 = ["op-connection-1", "op-connection-2"];
Mars mars;
address notOwner = vm.addr(1);
ChannelEnd ch0 =
Expand Down
23 changes: 2 additions & 21 deletions test/Dispatcher/Dispatcher.proof.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,7 @@ import {ChannelHandshakeSetting} from "../utils/Dispatcher.base.t.sol";
import {DummyLightClient} from "../../contracts/utils/DummyLightClient.sol";
import {DispatcherSendPacketTestSuite, ChannelOpenTestBaseSetup} from "./Dispatcher.t.sol";

contract DispatcherProofTestUtils is Base {
using stdStorage for StdStorage;

function load_proof(string memory filepath) internal returns (Ics23Proof memory) {
(bytes32 apphash, Ics23Proof memory proof) =
abi.decode(vm.parseBytes(vm.readFile(string.concat(rootDir, filepath))), (bytes32, Ics23Proof));

// this loads the app hash we got from the testing data into the consensus state manager internals
// at the height it's supposed to go. That is, a block less than where the proof was generated from.
stdstore.target(address(opLightClient)).sig("consensusStates(uint256)").with_key(proof.height - 1).checked_write(
apphash
);
// trick the fraud time window check
vm.warp(block.timestamp + 1);

return proof;
}
}

abstract contract DispatcherIbcWithRealProofsSuite is IbcEventsEmitter, DispatcherProofTestUtils {
abstract contract DispatcherIbcWithRealProofsSuite is IbcEventsEmitter, Base {
Mars mars;

ChannelEnd ch0;
Expand All @@ -60,7 +41,7 @@ abstract contract DispatcherIbcWithRealProofsSuite is IbcEventsEmitter, Dispatch
dispatcherProxy.channelOpenTry(ch1, ChannelOrder.NONE, false, connectionHops1, ch0, proof);
}

function test_ibc_channel_ack_123_a() public {
function test_ibc_channel_ack() public {
Ics23Proof memory proof = load_proof("/test/payload/channel_ack_pending_proof.hex");

vm.expectEmit(true, true, true, true);
Expand Down
7 changes: 1 addition & 6 deletions test/Dispatcher/Dispatcher.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {IbcReceiver} from "../../contracts/interfaces/IbcReceiver.sol";
import {DummyLightClient} from "../../contracts/utils/DummyLightClient.sol";
import "../../contracts/examples/Mars.sol";
import "../../contracts/core/OptimisticLightClient.sol";
import "../utils/Dispatcher.base.t.sol";
import {LocalEnd, ChannelHandshakeSetting, Base} from "../utils/Dispatcher.base.t.sol";
import {Earth} from "../../contracts/examples/Earth.sol";

abstract contract ChannelHandshakeUtils is Base {
Expand Down Expand Up @@ -293,11 +293,6 @@ contract PacketSenderTestBase is ChannelOpenTestBaseSetup {
function genPacket(uint64 packetSeq) internal view returns (IbcPacket memory) {
return IbcPacket(src, dest, packetSeq, payload, ZERO_HEIGHT, maxTimeout);
}

// genAckPacket generates an ack packet for the given packet sequence
function genAckPacket(string memory packetSeq) internal pure returns (bytes memory) {
return ackToBytes(AckPacket(true, bytes(packetSeq)));
}
}

// Test Chains B receives a packet from Chain A
Expand Down
108 changes: 81 additions & 27 deletions test/upgradeableProxy/Dispatcher.upgrade.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,35 @@ import "../../contracts/core/OptimisticLightClient.sol";
import {ChannelHandshakeTestSuite, ChannelHandshakeTest, ChannelHandshakeUtils} from "../Dispatcher/Dispatcher.t.sol";
import {LocalEnd} from "../utils/Dispatcher.base.t.sol";
import {Base, ChannelHandshakeSetting} from "../utils/Dispatcher.base.t.sol";
import {ChannelEnd, ChannelOrder, IbcEndpoint, IbcPacket, AckPacket, Ibc, Height} from "../../contracts/libs/Ibc.sol";
import {
ChannelEnd,
ChannelOrder,
ChannelState,
IbcEndpoint,
IbcPacket,
AckPacket,
Ibc,
Height
} from "../../contracts/libs/Ibc.sol";
import {IbcUtils} from "../../contracts/libs/IbcUtils.sol";
import {IbcReceiver} from "../../contracts/interfaces/IbcReceiver.sol";
import {IbcReceiver, IbcChannelReceiver} from "../../contracts/interfaces/IbcReceiver.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import {OptimisticLightClient} from "../../contracts/core/OptimisticLightClient.sol";
import {IProofVerifier} from "../../contracts/core/OptimisticProofVerifier.sol";
import {DummyLightClient} from "../../contracts/utils/DummyLightClient.sol";

import {IDispatcher} from "../../contracts/interfaces/IDispatcher.sol";
import {DispatcherRc4} from "./upgrades/DispatcherRc4.sol";
import {DispatcherV2Initializable} from "./upgrades/DispatcherV2Initializable.sol";
import {DispatcherV2} from "./upgrades/DispatcherV2.sol";
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

abstract contract UpgradeTestUtils {
string[] connectionHops0 = ["dummy-connection-1", "dummy-connection-2"];
string[] connectionHops1 = ["connection-1", "connection-2"];
LocalEnd _localDummy;
ChannelEnd _remoteDummy;

function upgradeDispatcher(string memory portPrefix, address dispatcherProxy)
public
returns (DispatcherV2Initializable newDispatcherImplementation)
Expand All @@ -31,48 +47,74 @@ abstract contract UpgradeTestUtils {
bytes memory initData = abi.encodeWithSignature("initialize(string)", portPrefix);
UUPSUpgradeable(dispatcherProxy).upgradeToAndCall(address(newDispatcherImplementation), initData);
}

function deployDispatcherRC4ProxyAndImpl(string memory initPortPrefix, ILightClient initLightClient)
public
returns (IDispatcher proxy)
{
DispatcherRc4 dispatcherImplementation = new DispatcherRc4();
bytes memory initData =
abi.encodeWithSelector(DispatcherRc4.initialize.selector, initPortPrefix, initLightClient);
proxy = IDispatcher(address(new ERC1967Proxy(address(dispatcherImplementation), initData)));
}
}

contract ChannelHandShakeUpgradeUtil is ChannelHandshakeUtils {
uint32 nextSequenceSendSlot = 153;
uint32 sendPacketCommitmentSlot = 156;
uint32 ackPacketCommitmentSlot = 158;
uint32 nextSequenceAckSlot = 155;
uint32 nextSequenceRecvSlot = 154;
IbcPacket[3] packets;
string payload = "msgPayload";
bytes packet = abi.encodePacked(payload);
uint64 timeoutTimestamp = 1000;

function doChannelHandshake() public {
// Conduct 4-step channel handshake between localChannelEnd and remoteChannelEnd end
// Have to pass in receivingDapp because it's hard to parse out the addresss from the portId
function doChannelHandshake(LocalEnd memory localEnd, ChannelEnd memory remoteEnd, IbcChannelReceiver receivingDapp)
public
{
// same setup as that run in test_connectChannel_ok
ChannelHandshakeSetting[8] memory settings = createSettings2(true);

string[2] memory versions = ["1.0", "2.0"];
for (uint256 i = 0; i < settings.length; i++) {
for (uint256 j = 0; j < versions.length; j++) {
LocalEnd memory le = _local;
ChannelEnd memory re = _remote;
le.versionCall = versions[j];
le.versionExpected = versions[j];
re.version = versions[j];
channelOpenInit(le, re, settings[i], true);
channelOpenTry(le, re, settings[i], true);
channelOpenAck(le, re, settings[i], true);
channelOpenConfirm(le, re, settings[i], true);
localEnd.versionCall = versions[j];
localEnd.versionExpected = versions[j];
remoteEnd.version = versions[j];
channelOpenInit(localEnd, remoteEnd, settings[i], true);
channelOpenTry(localEnd, remoteEnd, settings[i], true);
channelOpenAck(localEnd, remoteEnd, settings[i], true);
channelOpenConfirm(localEnd, remoteEnd, settings[i], true);
}
}
}

function sendOnePacket(bytes32 channelId, uint64 packetSeq) public {
function doProofChannelHandshake(
LocalEnd memory localEnd,
ChannelEnd memory remoteEnd,
IbcChannelReceiver receivingDapp
) public {
ChannelHandshakeSetting memory setting = ChannelHandshakeSetting(ChannelOrder.ORDERED, false, true, validProof);

channelOpenInit(localEnd, remoteEnd, setting, true);
channelOpenTry(localEnd, remoteEnd, setting, true);
channelOpenAck(localEnd, remoteEnd, setting, true);
channelOpenConfirm(localEnd, remoteEnd, setting, true);
}

function sendOnePacket(bytes32 channelId, uint64 packetSeq, Mars sender) public {
vm.expectEmit(true, true, true, true);
emit SendPacket(address(mars), channelId, packet, packetSeq, timeoutTimestamp);
mars.greet(payload, channelId, timeoutTimestamp);
emit SendPacket(address(sender), channelId, packet, packetSeq, timeoutTimestamp);
sender.greet(payload, channelId, timeoutTimestamp);
}

function sendPacket(bytes32 channelId) public {
for (uint64 index = 0; index < 3; index++) {
uint64 packetSeq = index + 1;
sendOnePacket(channelId, packetSeq);
sendOnePacket(channelId, packetSeq, mars);
IbcEndpoint memory dest = IbcEndpoint("polyibc.bsc.9876543210", "channel-99");
string memory marsPort = string(abi.encodePacked(portPrefix, getHexBytes(address(mars))));
IbcEndpoint memory src = IbcEndpoint(marsPort, channelId);
Expand All @@ -87,7 +129,7 @@ contract ChannelHandShakeUpgradeUtil is ChannelHandshakeUtils {
slot = keccak256(abi.encode(channelId, slot1));
}

function findPacketCommitmentSlot(address portAddress, bytes32 channelId, uint64 sequence)
function findSendPacketCommitmentSlot(address portAddress, bytes32 channelId, uint64 sequence)
public
view
returns (bytes32 slot)
Expand All @@ -97,6 +139,16 @@ contract ChannelHandShakeUpgradeUtil is ChannelHandshakeUtils {
slot = keccak256(abi.encode(sequence, slot2));
}

function findAckPacketCommitmentSlot(address portAddress, bytes32 channelId, uint64 sequence)
public
view
returns (bytes32 slot)
{
bytes32 slot1 = keccak256(abi.encode(portAddress, ackPacketCommitmentSlot));
bytes32 slot2 = keccak256(abi.encode(channelId, slot1));
slot = keccak256(abi.encode(sequence, slot2));
}

function findNextSequenceAck(address portAddress, bytes32 channelId) public view returns (bytes32 slot) {
bytes32 slot1 = keccak256(abi.encode(portAddress, nextSequenceAckSlot));
slot = keccak256(abi.encode(channelId, slot1));
Expand All @@ -110,37 +162,39 @@ contract ChannelHandShakeUpgradeUtil is ChannelHandshakeUtils {

contract DispatcherUpgradeTest is ChannelHandShakeUpgradeUtil, UpgradeTestUtils {
function setUp() public override {
address targetMarsAddress = 0x71C95911E9a5D330f4D621842EC243EE1343292e;
(dispatcherProxy, dispatcherImplementation) = deployDispatcherProxyAndImpl(portPrefix);
deployCodeTo("contracts/examples/Mars.sol:Mars", abi.encode(address(dispatcherProxy)), targetMarsAddress);
dispatcherProxy.setClientForConnection(connectionHops[0], dummyLightClient);
mars = new Mars(dispatcherProxy);
portId = IbcUtils.addressToPortId(portPrefix, address(mars));
_local = LocalEnd(mars, portId, "channel-1", connectionHops, "1.0", "1.0");
_remote = ChannelEnd("eth2.7E5F4552091A69125d5DfCb7b8C2659029395Bdf", "channel-2", "1.0");
string memory sendingPortId = IbcUtils.addressToPortId(portPrefix, address(mars));
string memory receivingPortId = IbcUtils.addressToPortId(portPrefix, targetMarsAddress);
_local = LocalEnd(mars, sendingPortId, "channel-1", connectionHops, "1.0", "1.0");
_remote = ChannelEnd(receivingPortId, "channel-2", "1.0");

// Add state to test if impacted by upgrade
doChannelHandshake();
doChannelHandshake(_local, _remote, IbcChannelReceiver(targetMarsAddress));
sendPacket(_local.channelId);

// Upgrade dispatcherProxy for tests
upgradeDispatcher("adfsafsa", address(dispatcherProxy));
}

function test_SentPacketState_Conserved() public {
// Check packet state in sendPacketCommitment()[]
uint64 nextSequenceSendValue = uint64(
uint256(vm.load(address(dispatcherProxy), findNextSequenceSendSlot(address(mars), _local.channelId)))
);

assertEq(4, nextSequenceSendValue);

// packets
assert(vm.load(address(dispatcherProxy), findPacketCommitmentSlot(address(mars), _local.channelId, 1)) > 0);
assert(vm.load(address(dispatcherProxy), findPacketCommitmentSlot(address(mars), _local.channelId, 2)) > 0);
assert(vm.load(address(dispatcherProxy), findPacketCommitmentSlot(address(mars), _local.channelId, 3)) > 0);
assert(vm.load(address(dispatcherProxy), findSendPacketCommitmentSlot(address(mars), _local.channelId, 1)) > 0);
assert(vm.load(address(dispatcherProxy), findSendPacketCommitmentSlot(address(mars), _local.channelId, 2)) > 0);
assert(vm.load(address(dispatcherProxy), findSendPacketCommitmentSlot(address(mars), _local.channelId, 3)) > 0);

// Test sending packet with the updated contract
sendOnePacket(_local.channelId, 4);
assert(vm.load(address(dispatcherProxy), findPacketCommitmentSlot(address(mars), _local.channelId, 4)) > 0);
sendOnePacket(_local.channelId, 4, mars);
assert(vm.load(address(dispatcherProxy), findSendPacketCommitmentSlot(address(mars), _local.channelId, 4)) > 0);
uint64 nextSequenceSendAfterSending = uint64(
uint256(vm.load(address(dispatcherProxy), findNextSequenceSendSlot(address(mars), _local.channelId)))
);
Expand Down
Loading

0 comments on commit 70df3c0

Please sign in to comment.