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

Raunak/dispatcher upgrade testing #81

Merged
merged 1 commit into from
May 7, 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
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
102 changes: 75 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;

RnkSngh marked this conversation as resolved.
Show resolved Hide resolved
function upgradeDispatcher(string memory portPrefix, address dispatcherProxy)
public
returns (DispatcherV2Initializable newDispatcherImplementation)
Expand All @@ -31,48 +47,68 @@ 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) 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) 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);
RnkSngh marked this conversation as resolved.
Show resolved Hide resolved
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 +123,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 +133,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 +156,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);
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
Loading