Skip to content

Commit

Permalink
Bedrock prod (#4414)
Browse files Browse the repository at this point in the history
* refactor: look at me; i am bedrock now

* refactor: remove configuration from deployment

* feat: redeploy hub connector

* feat: update subgraph hub connector address

* fix: lighthouse tests

* chore: update connector address

---------

Co-authored-by: Layne Haber <layne.haber@gmail.com>
  • Loading branch information
Rahul Sethuram and LayneHaber authored Jun 6, 2023
1 parent b633c37 commit 142551c
Show file tree
Hide file tree
Showing 7 changed files with 242 additions and 317 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,70 +37,50 @@ export const getProcessFromOptimismRootArgs = async ({
// uint256 _messageNonce, -> ?
// L2MessageInclusionProof memory _proof -> taken from sdk

const isBedrock = spokeChainId === 420;

// create the messenger
const messenger = new CrossChainMessenger({
l2ChainId: spokeChainId,
l2SignerOrProvider: new providers.JsonRpcProvider(spokeProvider),
l1ChainId: hubChainId,
l1SignerOrProvider: new providers.JsonRpcProvider(hubProvider),
bedrock: isBedrock,
bedrock: true,
});

if (isBedrock) {
// Handle bedrock proof
const status = await messenger.getMessageStatus(sendHash);
if (status !== MessageStatus.READY_TO_PROVE) {
throw new Error(`Optimism message status is not ready to prove: ${status}`);
}
// get the message
const resolved = await messenger.toCrossChainMessage(sendHash);
const {
messageNonce: nonce,
sender,
target,
value,
message: data,
minGasLimit: gasLimit,
} = await messenger.toLowLevelMessage(resolved);

// get the tx
const tx = {
nonce: nonce.toString(),
sender,
target,
value,
gasLimit,
data,
};
logger.info("Got withdrawal tx from optimism", requestContext, methodContext, { tx, isBedrock });

// get the proof
const proof = await messenger.getBedrockMessageProof(sendHash);
logger.info("Got L2 message proof from optimism", requestContext, methodContext, { proof, isBedrock });
if (!proof) {
throw new NoRootAvailable(spokeChainId, hubChainId, requestContext, methodContext);
}
const { l2OutputIndex, outputRootProof, withdrawalProof } = proof;

// Format arguments
return [tx, l2OutputIndex, outputRootProof, withdrawalProof];
// Handle bedrock proof
const status = await messenger.getMessageStatus(sendHash);
if (status !== MessageStatus.READY_TO_PROVE) {
throw new Error(`Optimism message status is not ready to prove: ${status}`);
}

// check to make sure you can prove
const root = await messenger.getMessageStateRoot(sendHash);
if (!root) {
// get the message
const resolved = await messenger.toCrossChainMessage(sendHash);
const {
messageNonce: nonce,
sender,
target,
value,
message: data,
minGasLimit: gasLimit,
} = await messenger.toLowLevelMessage(resolved);

// get the tx
const tx = {
nonce: nonce.toString(),
sender,
target,
value,
gasLimit,
data,
};
logger.info("Got withdrawal tx from optimism", requestContext, methodContext, { tx });

// get the proof
const proof = await messenger.getBedrockMessageProof(sendHash);
logger.info("Got L2 message proof from optimism", requestContext, methodContext, { proof });
if (!proof) {
throw new NoRootAvailable(spokeChainId, hubChainId, requestContext, methodContext);
}
const { l2OutputIndex, outputRootProof, withdrawalProof } = proof;

// get the message to get the message nonce
const [message] = await messenger.getMessagesByTransaction(sendHash);
logger.info("Got message from optimism", requestContext, methodContext, { message });

// get the inclusion proof
const proof = await messenger.getMessageProof(sendHash);
logger.info("Got proof from optimism", requestContext, methodContext, { proof });

return [message.target, message.sender, message.message, message.messageNonce, proof];
// Format arguments
return [tx, l2OutputIndex, outputRootProof, withdrawalProof];
};
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
import { createRequestContext, expect, mkAddress, mkBytes32, mkHash } from "@connext/nxtp-utils";
import { stub, SinonStub } from "sinon";
import { CrossChainMessage, CrossChainMessageProof } from "@eth-optimism/sdk";
import { CrossChainMessage, MessageStatus } from "@eth-optimism/sdk";

import * as MockableFns from "../../../../src/mockable";
import { getProcessFromOptimismRootArgs } from "../../../../src/tasks/processFromRoot/helpers";
import { NoRootAvailable } from "../../../../src/tasks/processFromRoot/errors";
import { BigNumber, constants } from "ethers";

let getMessageStateRootStub: SinonStub;
let getMessagesByTransactionStub: SinonStub;
let getMessageProofStub: SinonStub;
let getMessageStatusStub: SinonStub;
let toCrosschainMessageStub: SinonStub;
let toLowLevelMessageStub: SinonStub;
let getBedrockMessageProofStub: SinonStub;

// TODO: need to import from sdk but not in types
interface BedrockCrossChainMessageProof {
l2OutputIndex: number;
outputRootProof: string[];
withdrawalProof: string[];
}

class MockCrossChainMessenger {
public getMessageStateRoot = getMessageStateRootStub;
public getMessagesByTransaction = getMessagesByTransactionStub;
public getMessageProof = getMessageProofStub;
public getMessageStatus = getMessageStatusStub;
public toCrossChainMessage = toCrosschainMessageStub;
public getBedrockMessageProof = getBedrockMessageProofStub;
public toLowLevelMessage = toLowLevelMessageStub;
}

const mockCrossChainMessage: CrossChainMessage = {
Expand All @@ -30,30 +39,41 @@ const mockCrossChainMessage: CrossChainMessage = {
value: constants.Two,
};

const mockCrossChainMessageProof: CrossChainMessageProof = {
stateRoot: mkBytes32("0xdeadbeef"),
stateRootBatchHeader: {
batchIndex: constants.One,
batchRoot: mkBytes32("0xbbb"),
batchSize: constants.Two,
extraData: "0xfee",
prevTotalElements: constants.Zero,
},
stateRootProof: { index: 42, siblings: [] },
stateTrieWitness: mkAddress("0xdeaf"),
storageTrieWitness: mkAddress("0xddbeef"),
const mockCrossChainMessageProof: BedrockCrossChainMessageProof = {
l2OutputIndex: 1235,
outputRootProof: [mkBytes32("0xdeaf")],
withdrawalProof: [mkBytes32("0xddbeef")],
};

describe("Helpers: Optimism", () => {
beforeEach(() => {
stub(MockableFns, "CrossChainMessenger").value(MockCrossChainMessenger);
getMessageStateRootStub = stub().resolves(mkHash("0xdeadbeef"));
getMessagesByTransactionStub = stub().resolves([mockCrossChainMessage]);
getMessageProofStub = stub().resolves(mockCrossChainMessageProof);
getMessageStatusStub = stub().resolves(MessageStatus.READY_TO_PROVE);
toCrosschainMessageStub = stub().resolves(mockCrossChainMessage);
toLowLevelMessageStub = stub().resolves(mockCrossChainMessage);
getBedrockMessageProofStub = stub().resolves(mockCrossChainMessageProof);
});

it("should throw error if status is not ready to prove", async () => {
getMessageStatusStub.resolves(MessageStatus.STATE_ROOT_NOT_PUBLISHED);
await expect(
getProcessFromOptimismRootArgs({
spokeChainId: 1,
spokeDomainId: "1",
spokeProvider: "world",
hubChainId: 2,
hubDomainId: "2",
hubProvider: "hello",
sendHash: mkHash("0xbaa"),
_requestContext: createRequestContext("foo"),
message: "0xbabababababa",
blockNumber: 1,
}),
).to.be.rejectedWith(`Optimism message status is not ready to prove: ${MessageStatus.STATE_ROOT_NOT_PUBLISHED}`);
});

it("should throw error if undefined", async () => {
getMessageStateRootStub.resolves(undefined);
it("should throw error if no proof found", async () => {
getBedrockMessageProofStub.resolves(undefined);
await expect(
getProcessFromOptimismRootArgs({
spokeChainId: 1,
Expand All @@ -64,6 +84,8 @@ describe("Helpers: Optimism", () => {
hubProvider: "hello",
sendHash: mkHash("0xbaa"),
_requestContext: createRequestContext("foo"),
message: "0xbabababababa",
blockNumber: 1,
}),
).to.be.rejectedWith(NoRootAvailable);
});
Expand All @@ -78,13 +100,21 @@ describe("Helpers: Optimism", () => {
hubProvider: "hello",
sendHash: mkHash("0xbaa"),
_requestContext: createRequestContext("foo"),
message: "0xbabababababa",
blockNumber: 1,
});
expect(args).to.deep.eq([
mockCrossChainMessage.target,
mockCrossChainMessage.sender,
mockCrossChainMessage.message,
mockCrossChainMessage.messageNonce,
mockCrossChainMessageProof,
{
nonce: mockCrossChainMessage.messageNonce.toString(),
target: mockCrossChainMessage.target,
sender: mockCrossChainMessage.sender,
data: mockCrossChainMessage.message,
value: mockCrossChainMessage.value,
gasLimit: mockCrossChainMessage.minGasLimit,
},
mockCrossChainMessageProof.l2OutputIndex,
mockCrossChainMessageProof.outputRootProof,
mockCrossChainMessageProof.withdrawalProof,
]);
});
});
16 changes: 2 additions & 14 deletions packages/deployments/contracts/deploy/01_deployMessaging.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction, DeployResult } from "hardhat-deploy/types";
import { BigNumber, constants, Wallet } from "ethers";
import { constants, Wallet } from "ethers";
import { chainIdToDomain } from "@connext/nxtp-utils";

import { getConnectorName, getDeploymentName, getProtocolNetwork, deployBeaconProxy } from "../src";
import { MessagingProtocolConfig, MESSAGING_PROTOCOL_CONFIGS } from "../deployConfig/shared";
import { chainIdToDomain } from "@connext/nxtp-utils";

// Format the arguments for Connector contract constructor.
const formatConnectorArgs = (
Expand Down Expand Up @@ -113,18 +113,6 @@ const handleDeployHub = async (
});
console.log(`RootManager deployed to ${rootManager.address}`);

// setArborist to Merkle for RootManager
const merkleForRootContract = await hre.ethers.getContractAt(
"MerkleTreeManager",
merkleTreeManagerForRoot.address,
deployer,
);
if (!(await merkleForRootContract.arborist())) {
const tx = await merkleForRootContract.setArborist(rootManager.address);
console.log(`setArborist for RootManager tx submitted:`, tx.hash);
await tx.wait();
}

// Deploy MerkleTreeManager(beacon proxy)
console.log("Deploying MerkleTreeManager proxy For MainnetSpokeConnector...");
const merkleTreeManagerForSpoke = await deployBeaconProxy(
Expand Down
Loading

0 comments on commit 142551c

Please sign in to comment.